418 lines
14 KiB
Markdown
418 lines
14 KiB
Markdown
# 生产服务监控告警与无停机发布方案
|
||
|
||
## 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`。
|