监控回答“系统现在怎样”,告警回答“是否需要人介入”,Runbook 回答“接到告警后先做什么”。三者必须从同一服务目标和故障模型推导,不能只因为某个指标容易采集就设置阈值。
信号到行动
最小 SLI 集合
| 范围 | 指标 | 为什么重要 |
|---|---|---|
| HTTP | 请求率、错误率、延迟分位数、并发 | 直接反映用户体验 |
| 数据库 | 连接池、超时、死锁/并发冲突、慢查询 | 发现共享瓶颈与容量风险 |
| CAP/RabbitMQ | 待发布、待消费、重试、最老消息年龄 | 发现最终一致性停滞 |
| JobHost | 调度延迟、成功/失败、重试、租约状态 | 发现后台闭环断裂 |
| Redis | 可达性、延迟、内存、逐出、锁降级 | 缓存、幂等与协调共同依赖 |
| 审计 | 队列深度、丢弃/失败、写入延迟 | 合规证据不能静默消失 |
| Adapter | 当前实现类型与 Readiness | 防止生产解析到默认/Unavailable |
阈值从测得的基线、容量和 SLO 推导。本手册不硬编码某个环境的百分位或队列数量;生产值进入监控配置,并在容量或版本变化后重新校准。
Kubernetes 探针示例
# ① Liveness 只判断进程是否需要重启,不能依赖短暂不可用的外部系统。livenessProbe: httpGet: { path: /health/live, port: 8080 } periodSeconds: 10
# ② Readiness 决定是否接流量,可包含当前请求必需的窄依赖探针。readinessProbe: httpGet: { path: /health/ready, port: 8080 } periodSeconds: 5 failureThreshold: 3告警设计
- 优先告警用户影响、错误预算消耗和持续积压,不告警每一次瞬时异常;
- Warning 给调查窗口,Critical 代表正在影响交付或数据安全;
- 每条告警包含服务、环境、租户范围(可安全提供时)、开始时间、Dashboard 和 Runbook;
- 使用脱敏关联 ID 连接日志与 Trace,不把 Secret 或个人信息放进 Label;
- 对“告警本身失效”设置 Dead Man/遥测缺失检测。
Runbook 模板
- 确认影响:哪些端点、租户、消息或作业受到影响?
- 判定依赖:Readiness、数据库、RabbitMQ、Redis、外部 Adapter 谁先异常?
- 控制风险:摘流量、暂停消费者、失败关闭高价值写入或回滚版本。
- 恢复事实:恢复依赖后核对 Outbox、幂等记录、任务状态和审计,没有重复或缺失。
- 验证服务:运行窄 Smoke、观察错误预算和积压下降,再完全恢复流量。
- 留下证据:时间线、根因、客户影响、临时措施、长期行动和 Owner。
告警演练至少覆盖数据库不可达、RabbitMQ 积压、Redis 锁 Deny、JobHost 停止、审计写入失败和错误 Adapter。详细信号语义见可观测性,灾难级恢复见灾难恢复。
当前 OTel 与健康语义
ServiceDefaults 统一注册 ASP.NET Core、HttpClient、Runtime 指标,框架 ActivitySource,以及 JobHost Quartz 和数据库慢查询 Meter。Trace、Metric、Log 都通过 OTEL_EXPORTER_OTLP_ENDPOINT 输出。
/health/live 只筛选 live tag 的 self check;/health/ready 只汇总 ready 依赖。兼容端点 /health 会运行全部检查,不能把它误用为轻量 liveness。
# ① 分开探测进程存活和依赖就绪,并保留 HTTP 状态与耗时。curl -fsS -o /dev/null -w 'live %{http_code} %{time_total}\n' "$URL/health/live"curl -fsS -o /dev/null -w 'ready %{http_code} %{time_total}\n' "$URL/health/ready"
# ② 用标准环境变量控制采样;先在 Staging 验证后再降低生产比例。export OTEL_TRACES_SAMPLER=parentbased_traceidratioexport OTEL_TRACES_SAMPLER_ARG=0.10告警与发布关联
Dashboard 至少按 service.name、service.version 与 deployment.environment 切分。发布标记应关联镜像摘要和 Commit,才能判断错误率变化来自新版本、依赖故障还是流量结构。
高基数 tenantId、userId、URL 原始 ID 不应成为 Metric label;需要租户调查时使用受控日志或 Trace 查询。
Runbook 验证
每条 Critical 告警至少季度演练一次:触发可控故障,确认通知路由、值班响应、止损权限、恢复命令和证据归档。只阅读 Runbook 不能证明它可执行。
Alert → owner acknowledged → impact scoped → traffic/consumer contained → dependency recovered → outbox/task/audit reconciled → narrow smoke → backlog drains → close with timeline完成清单
- live 与 ready 的依赖集合符合重启/摘流量语义;
- OTel Collector 不可用不会静默耗尽应用内存或磁盘;
- 告警覆盖用户影响、错误预算和持续积压;
- 每条告警有 owner、Dashboard、Runbook 与升级路径;
- 发布、事故、回滚和恢复能够用 correlation/trace 串联;
- 遥测缺失本身有 Dead Man 告警。
首个 Dashboard
按 API、JobHost、数据库、消息与 Redis 分五行展示:流量/吞吐、错误、延迟、饱和度和最近发布标记。每个面板链接对应日志或 Trace 查询,并明确时区与采样率。
Dashboard 不展示无 Owner 的“漂亮指标”。每个图要么支持 SLO、容量、发布判断或 Runbook,要么删除。
部署后至少观察一个完整业务高峰,并比较发布前基线。低流量环境使用合成 smoke 和作业心跳,避免“没有数据”被当成健康。
对 CAP、审计和 JobHost 使用最老积压年龄,而不只看数量;数量不变但年龄持续上升通常更能说明闭环停止。
- 视图默认展示当前环境,同时允许对照上一版本;
- 关键查询保存为代码并经过评审;
- Dashboard 变更跟随发布版本;
- 长期趋势用于容量,短窗口用于事故;
- 权限确保租户与个人数据不会越权暴露。