# 服务器离线告警 — 设计

**日期**: 2026-06-08  
**状态**: 已实现

## 背景与目标

运维需要在子机 Agent 停止上报或心跳过期时，通过 Telegram **主动通知一次**（非重复轰炸），并在系统设置中提供独立开关。

## 方案对比

| 方案 | 优点 | 缺点 |
|------|------|------|
| A. 在 `heartbeat_flush`（10min）检测 | 改动小 | 离线发现延迟可达 10 分钟 |
| B. 独立 30s 轮询 + 边沿触发 | 与 `self_monitor` 一致；与列表 `offline` 判定同源 | 新增后台任务 |
| C. 仅在 Agent 心跳 `is_online=false` | 实时 | Agent 宕机时无心跳，无法覆盖 |

**选定 B**：`server_offline_monitor` 每 30s 扫描已监控子机 Redis `heartbeat:{id}`，与 `server_connectivity` 相同规则判定在线；**在线→离线**边沿触发一次 Telegram + `alert_logs` + WebSocket 刷新。

## 接口与数据

- 设置键：`notify_alert_offline` → `NOTIFY_ALERT_OFFLINE`（默认 `true`）
- `alert_logs.alert_type` = `offline`
- Telegram：`send_telegram_offline_alert`；关闭开关时不发送
- 防抖：边沿触发为主；`_should_push_telegram(alert:{id}:offline)` 5min 兜底

## 安全与性能

- 仅 primary worker 运行；批量 pipeline 读 Redis，200 台/批
- 冷启动：首次扫描只记录状态，不对已离线机群发历史告警

## 验收标准

1. 子机从在线变为离线后 30s 内收到 Telegram（开关开启且 Bot 已配置）
2. 持续离线不重复推送；恢复后再离线可再次推送
3. 设置页可关闭 `notify_alert_offline`，关闭后无 Telegram
4. `alert_logs` 有 `offline` 记录；仪表盘 WS 触发刷新
