Files
docs/生产服务监控告警与无停机发布方案.md
T
2026-09-21 07:59:51 +08:00

418 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 生产服务监控告警与无停机发布方案
## 1. 文档状态与目标
- 状态:待实施。
- 当前动作:只记录方案,不修改生产环境、Jenkins、Compose 或告警配置。
- 适用范围:国内生产、海外生产、Nacos、RocketMQ、Gateway、Admin、Client 及全部业务服务。
目标:
1. 服务退出、失去健康状态或无法对外提供业务时能够及时通知。
2. 服务具备合理的自动恢复能力,避免有限重试耗尽后永久停止。
3. 正常发布期间减少无意义告警,但不掩盖部署失败和超时。
4. 逐步从单实例短暂停服发布升级为可验证的滚动或蓝绿发布。
## 2. 当前问题与事故事实
### 2.1 已有能力
- ECS 已配置 CPU、内存超过 80% 告警。
- Jenkins 已具备部分生产部署成功、失败和取消通知。
- 服务镜像包含 Docker 健康检查。
- 单服务部署失败后具备自动回滚逻辑。
### 2.2 当前缺口
CPU、内存告警不能代表服务可用性。服务停止后 CPU 和内存使用率可能下降,因此不会触发资源阈值告警。
当前还缺少:
- 容器退出告警。
- 容器 `unhealthy` 告警。
- 外部 HTTPS 可用性告警。
- Nacos 实例数量下降告警。
- RocketMQ NameServer、Broker 可用性及消息堆积告警。
- 自动恢复耗尽告警。
- 部署开始、回滚成功、回滚失败和部署超时通知。
- 部署期间的精确维护窗口。
### 2.3 2026-09-18 File Service 发布失败
故障链路:
1. RocketMQ NameServer 曾收到 `SIGKILL`,退出码为 `137`。
2. Docker 未记录容器级 OOM,宿主机内核也没有 OOM 记录。
3. NameServer 使用 `restart: on-failure:3`,三次重试耗尽后永久停止。
4. Broker 容器仍在运行,但新启动的 File Service 无法通过 NameServer 获取 Topic 路由。
5. File Service 新镜像启动失败,自动回滚到旧镜像后仍然失败。
6. 手工恢复 NameServer 并确认 Broker 重新注册后,旧版 File Service 恢复健康。
本次故障证明:
- “容器存在”不等于基础设施可用。
- 自动重启不是告警系统。
- 应用回滚不能解决外部依赖故障。
- 关键基础设施必须独立监控,不能等业务服务重新部署时才发现。
## 3. 监控分层
监控应同时覆盖资源、容器、应用、入口和业务依赖。
| 层级 | 监控对象 | 典型告警 |
|---|---|---|
| 主机资源 | CPU、内存、磁盘、inode、负载、网络 | 持续高使用率、磁盘将满、网络异常 |
| Docker | 容器状态、健康状态、重启次数 | exited、unhealthy、频繁重启、容器缺失 |
| 应用 | `/actuator/health`、JVM、连接池 | 健康检查失败、线程/连接池耗尽 |
| 外部入口 | Admin、Client、国内/海外 Gateway | HTTPS 不通、5xx、超时、证书异常 |
| 服务发现 | Nacos 服务实例与健康实例数 | 核心服务无健康实例、实例数异常下降 |
| 消息系统 | NameServer、Broker、Topic、Consumer Group | 端口不通、Broker 未注册、消息堆积、死信增长 |
| 数据服务 | RDS、Redis | 连接失败、慢 SQL、连接数、容量、主从切换 |
| 发布系统 | Jenkins 构建和部署阶段 | 发布失败、超时、回滚失败、版本不一致 |
任何单一层级都不能替代其他层级。
## 4. 告警规则建议
### 4.1 主机资源
当前 CPU、内存 80% 告警继续保留,并建议增加持续时间,避免瞬时峰值产生噪声。
| 指标 | 建议规则 |
|---|---|
| CPU | 超过 80% 持续 5 分钟告警;超过 95% 持续 2 分钟升级 |
| 内存 | 超过 80% 持续 5 分钟告警;可用内存持续过低升级 |
| 数据盘 | 使用率超过 80% 告警,超过 90% 升级 |
| inode | 使用率超过 80% 告警 |
| Load | 持续显著超过 CPU 核数告警 |
| 网络 | 连接失败、丢包或带宽长期打满告警 |
### 4.2 容器状态
关键容器包括:
- Nacos。
- RocketMQ NameServer、Broker。
- 国内和海外 Gateway。
- Auth、IAM、File、Event Bridge 等核心服务。
- Admin、Client 前端容器。
告警规则:
- 容器进入 `exited`:立即通知。
- 容器进入 `unhealthy`:连续两次检测失败后通知。
- 预期容器不存在:立即通知。
- 10 分钟内重启超过 3 次:高优先级通知。
- 告警恢复后必须发送恢复通知,包含中断时长。
### 4.3 外部可用性
至少从生产 ECS 之外检查:
- `https://admin.buggoglobal.com/`
- `https://app.buggoglobal.com/`
- 国内 Gateway 轻量健康接口。
- 海外 Gateway 轻量健康接口。
建议每 30 秒检查一次,连续失败 3 次后告警。检查内容包括:
- DNS 解析。
- TLS 证书与握手。
- HTTP 状态码。
- 响应时间。
- 返回内容是否符合预期。
只在 ECS 内部探测不能发现公网 DNS、证书、反向代理或安全组问题。
### 4.4 RocketMQ
至少检查:
- NameServer 9876 端口可连接。
- Broker 能被 `clusterList` 查询到且为激活状态。
- 关键 Topic 存在。
- 关键 Consumer Group 存在。
- 消息堆积量和最老消息年龄。
- 死信队列增长。
不能只检查 Broker 容器运行状态。本次事故中 Broker 仍运行,但 NameServer 已停止。
### 4.5 Nacos
至少检查:
- Nacos API/控制台可用。
- 国内、海外命名空间可以认证读取。
- 每个应运行服务存在健康实例。
- 核心服务健康实例数变为 0 时立即告警。
## 5. 自动恢复策略
### 5.1 长期运行容器
后续评审通过后,长期运行容器建议使用:
```yaml
restart: unless-stopped
```
适用于 Nacos、RocketMQ NameServer、RocketMQ Broker、Gateway 和业务服务。
该策略只负责恢复进程,不代表服务一定健康,也不能代替告警。
### 5.2 一次性任务
初始化和迁移任务不能使用无限重启,例如:
- RocketMQ Topic 初始化。
- 数据库迁移。
- 一次性数据任务。
这些任务应在失败后停止并通知,避免无限重复执行有副作用的动作。
### 5.3 恢复边界
自动恢复不能执行:
- 清空数据库或缓存。
- 自动修改配置中心。
- 自动执行 Flyway `repair`。
- 自动忽略启动错误。
- 跨服务随意重启全部容器。
## 6. Jenkins 发布通知
生产部署每次至少发送四类事件。
### 6.1 开始部署
通知内容:
- 环境和区域。
- 服务名称。
- Git commit。
- 镜像标签。
- Jenkins 构建号和链接。
- 操作来源。
### 6.2 部署成功
通知内容:
- 新镜像版本。
- 健康检查结果。
- 部署耗时。
- 是否发生容器重建。
### 6.3 部署失败
通知内容:
- 失败阶段。
- 首个有效错误摘要。
- 新容器状态。
- 是否已触发回滚。
### 6.4 回滚结果
必须区分:
- 回滚成功:旧镜像恢复健康。
- 回滚失败:旧镜像也未恢复,应升级为高优先级事故。
## 7. 部署期间的告警处理
### 7.1 不关闭全局监控
发布时不能关闭整台 ECS、整个区域或全部服务告警。只允许为正在部署的目标服务建立短时维护标记。
### 7.2 精确维护窗口
单实例发布阶段可采用:
1. Jenkins 发布开始时写入目标服务维护标记,默认有效期 3~5 分钟。
2. 维护期间普通短时健康失败不立即通知。
3. 容器启动失败、回滚失败和维护超时仍立即通知。
4. 发布成功后立即删除维护标记,不等待 TTL 自然过期。
5. Jenkins 异常退出时,维护标记必须依靠 TTL 自动失效。
维护标记必须精确到环境、区域和服务,不得用“生产维护中”屏蔽全部告警。
### 7.3 仍需告警的情况
即使在维护窗口内,以下情况也不能静默:
- Nacos、RocketMQ、RDS、Redis 等非目标基础设施故障。
- Gateway 或公网入口整体不可用。
- 部署超过预定时间。
- 新旧镜像均不健康。
- 自动回滚失败。
## 8. 当前单实例部署的限制
当前 Compose 使用相同服务名和容器名重建目标容器。发布过程中旧容器会停止,新容器完成启动和健康检查前可能存在短暂停服。
单实例模式下可以缩短中断,但无法真正保证无停机。仅延长告警等待时间也不能解决用户请求中断。
短期接受单实例时应:
- 在低峰期发布。
- 设置合理的健康检查启动宽限期。
- 提前拉取镜像。
- 保证配置、网络和依赖预检通过后再重建容器。
- 将可接受中断时间形成明确指标。
## 9. 无停机发布目标
### 9.0 当前单机蓝绿实现
生产业务应用已采用逐服务蓝绿,不同时复制整套应用。数据库、Redis、Nacos 和 RocketMQ
不参与应用槽位切换,继续按各自高可用方案运行。
- 后端槽位命名为 `firstleg-production-<service>-blue/green`,绿色槽使用基础宿主机端口加
`10000`;活动状态保存在 `/data/firstleg/deploy/blue-green-state/`。
- 候选 Web 槽先健康检查,再接入 `firstleg-production-routing` 网络;失败只删除候选,
不停止活动槽。
- 带 `@Scheduled` 或 MQ Consumer 的服务,Web 槽固定关闭后台任务;后台任务运行在不注册
Nacos、不暴露端口的单例 `*-worker` 容器。Worker 顺序切换,避免新旧任务双跑。
- 宝塔反向代理永久指向固定入口 `9000/9300/9001/9002`,部署脚本不得修改宝塔管理的
站点 vhost 文件。独立的 `00-blue-green-*.conf` 在固定入口后执行槽位切换。
- 国内、海外 Gateway 槽位分别使用 `19000/29000`、`19300/29300`,宿主机 Nginx
`nginx -t` 成功后才 reload;失败恢复切流层配置。
- Admin、Client 槽位分别使用 `19001/29001`、`19002/29002`,使用稳定的
`gateway-active`、`gateway-overseas-active` 路由别名。
- 所有 Java Web 槽使用优雅停机,默认最多等待 45 秒完成在途请求。
首次迁移顺序固定为:
```text
Admin -> Client
-> gateway -> gateway-overseas
-> auth -> iam -> order -> warehouse -> firstleg -> finance -> file -> print -> integration
-> audit -> event-bridge(CN/OVERSEAS) -> lastleg -> warehouse-overseas
```
Gateway 切换前会检查两个前端是否已经使用稳定别名;不满足时发布失败并保留旧 Gateway。
后续发布只双开当前目标服务,不要求整套业务同时占用双倍内存。
### 9.1 业务服务滚动发布
目标流程:
```text
旧实例继续接收请求
-> 启动新实例
-> 等待健康检查通过
-> 等待 Nacos 注册为健康实例
-> 将流量逐步交给新实例
-> 旧实例停止接收新请求
-> 等待在途请求完成
-> 停止旧实例
```
要求:
- 同一服务至少两个实例。
- 容器名称不能固定为唯一名称。
- 实例不能争用相同宿主机端口。
- 定时任务、消费者和 Worker 必须评估多实例行为。
- 应用必须支持优雅停机。
- 数据库变更必须遵守 Expand/Contract,详见数据库版本迁移方案。
### 9.2 Gateway 发布
Gateway 自身不能只依靠 Nacos。至少部署两个实例,并由 Nginx、ALB 或等价负载均衡器负责:
- 健康检查。
- 逐个摘除旧实例。
- 新实例验证后再接流量。
- 发布失败时继续使用旧实例。
### 9.3 Admin 与 Client
前端可采用蓝绿目录或蓝绿容器:
1. 新版本部署到非当前槽位。
2. 检查静态资源和首页。
3. 原子切换 Nginx upstream 或软链接。
4. 保留旧版本用于快速切回。
### 9.4 单 ECS 的边界
同一 ECS 上双实例可以解决发布中断和单容器故障,但不能防止:
- ECS 宕机。
- 数据盘故障。
- Docker daemon 故障。
- 整机网络故障。
真正的主机级高可用需要至少两台 ECS,并由负载均衡器进行健康检查和流量切换。
## 10. 告警等级与通知渠道
| 等级 | 示例 | 通知建议 |
|---|---|---|
| P1 | 国内/海外入口不可用、数据库不可用、回滚失败 | 企业微信 + 电话/短信,立即处理 |
| P2 | 核心服务无实例、NameServer/Broker 故障、持续高错误率 | 企业微信告警群,限时处理 |
| P3 | CPU/内存 80%、磁盘趋势、单次容器重启 | 企业微信运维群,工作时段跟进 |
所有告警应包含:
- 环境、区域、主机和服务。
- 开始时间和持续时间。
- 当前状态与最近变化。
- 可点击的日志或监控入口。
- 推荐的第一条只读诊断命令。
- 恢复通知。
通知不得包含密码、Token 或完整敏感连接串。
## 11. 分阶段实施建议
### 阶段 A:补齐发现能力
- 保留现有 CPU、内存 80% 告警。
- 增加磁盘、inode 和主机可用性告警。
- 增加关键容器退出、unhealthy、缺失及频繁重启告警。
- 增加 Admin、Client、国内/海外 Gateway 外部 HTTPS 探测。
- 增加 Nacos 健康实例和 RocketMQ NameServer/Broker 检查。
### 阶段 B:改进恢复与发布通知
- 评审并调整长期运行容器重启策略。
- Jenkins 增加开始、成功、失败和回滚结果通知。
- 增加目标服务级维护标记和超时保护。
- 发布前增加基础设施依赖预检。
### 阶段 C:降低发布中断
- 业务服务支持双实例。
- Nacos 下线与优雅停机接入发布脚本。
- Gateway 和前端采用蓝绿或滚动方式。
- 验证消费者、定时任务和文件服务的多实例安全。
### 阶段 D:主机级高可用
- 增加第二台生产 ECS。
- Gateway 接入 ALB 或等价负载均衡。
- 关键实例跨主机分布。
- 定期执行单实例故障和滚动发布演练。
## 12. 后续实施验收标准
- 手工停止任一关键容器后,规定时间内收到告警。
- 容器恢复后收到恢复通知并记录中断时长。
- NameServer 停止时能够在 File Service 发布前发现。
- 正常单服务部署不会触发无意义的普通可用性告警。
- 部署超时或回滚失败即使处于维护窗口也会告警。
- 告警明确区分应用失败、基础设施失败和资源压力。
- 重复告警受到抑制,但事故状态持续可见。
- 双实例发布阶段实际请求无明显中断。
- 监控系统故障本身也有独立告警。
## 13. 与其他文档的关系
- 数据库发布顺序和 Expand/Contract:`数据库版本迁移与Jenkins自动发布方案.md`。
- 阿里云资源、高可用、压测和整体上线:`阿里云生产环境选型压测与上线手册.md`。
- 测试环境持续部署:`测试环境Jenkins部署指南.md`。