背景
收到腾讯云监控告警:
告警对象:clb-deploy-ehz5w467 | VIP: 172.17.0.7
当前数据:85.171%(并发连接数利用率)
CLB 并发连接数利用率达到 85%,已接近上限。需要快速定位原因并修复。
Step 1:CloudQ 智能诊断
将告警信息提交给 CloudQ,请求分析 CLB 关联的 Nginx 错误日志和监控数据。CloudQ 返回了完整的诊断报告:
Step 2:根因分析
CloudQ 通过分析 Nginx 错误日志,精准定位了问题的恶性循环链路:
↓
Node.js 3000端口服务异常 → 连接重置/断开
↓
CLB 判定 RS 异常 → 持续重试健康检查(间隔极短)
↓
失败连接未及时释放 → HTTPS 443 连接数 5,734 → 47,000+
↓
并发连接利用率突破 85% → 触发告警
关键发现:
- HTTP 80 端口:活跃连接 0~1,完全正常
- HTTPS 443 端口:活跃连接从 5,734 持续攀升至 47,000+
- 两种 Nginx 错误交替出现:
upstream prematurely closed connection(进程崩溃中)和recv() failed (104)(进程已崩溃)
Step 3:修复措施
基于 CloudQ 的诊断结论,执行了以下修复:
| 优先级 | 措施 | 调整内容 | 效果 |
|---|---|---|---|
| P1 | CLB 健康检查间隔 | 5s → 15s | 连接堆积速率降低 3 倍 |
| P1 | 健康检查超时 | 2s → 5s | 减少因网络抖动导致的误判 |
| P2 | Node.js 内存限制 | 无限制 → 512MB | 防止 OOM 导致进程瞬时崩溃 |
健康检查配置调整
通过 CLB API 将两条 HTTPS 规则(fisher.cool + tsa-lab.cn)的健康检查间隔从 5 秒调整到 15 秒:
调整后:IntervalTime=15s, TimeOut=5s
不健康阈值:3次(不变)
检测路径:/health(不变)
Node.js 进程内存守护
为所有实例的 systemd 服务添加 V8 堆内存上限:
配合 systemd 的 Restart=always,即使进程因内存问题退出也会在 5 秒内自动恢复,缩短服务不可用窗口。
Step 4:验证
修复后验证所有节点健康:
- 跳板机 172.17.0.17 — 200 OK (29ms)
- 竞价实例 172.17.0.9 — 200 OK (1ms)
- 竞价实例 172.17.0.15 — 200 OK (2ms)
CLB 后端健康检查全部 Alive,并发连接数已恢复正常水位。
复盘
本次告警处理流程:
- 收到告警(并发连接利用率 85%)→ 提交给 CloudQ
- CloudQ 分析:读取 Nginx 错误日志 + CLB 监控数据 → 定位根因(后端服务异常 + 健康检查频率过高 → 连接堆积)
- 执行修复:调整健康检查间隔(5→15s) + 增加超时(2→5s) + Node.js 内存守护(512MB)
- 验证恢复:所有节点 200 OK,连接数正常
CloudQ 在本次事件中的价值:从 Nginx 错误日志中识别出"健康检查失败→连接堆积"的恶性循环模式,准确定位了告警根因不是流量激增,而是后端服务异常引发的内部连接风暴。这比人工逐一排查各组件效率高出数倍。
Step 5:根治——部署脚本改造为滚动重启
CloudQ 的分析揭示了一个关键事实:00:33 的 Connection refused 不是应用崩溃,而是 deploy.sh 部署时三台实例同时重启导致的。三台同时重启 → 服务中断 3-5 秒 → CLB 健康检查全部失败 → 连接堆积。
为了从根本上避免部署引发告警,我们将 deploy.sh 从"全量重启"改造为"滚动重启"模式:
| 阶段 | 改造前 | 改造后 |
|---|---|---|
| 文件同步 | 同步一台→立即重启→再同步下一台 | Phase 1:先同步全部实例(不重启) |
| 服务重启 | 所有实例几乎同时重启 | Phase 2:逐台重启,等健康检查通过后再重启下一台 |
| 服务可用性 | 全部不可用窗口 3-5 秒 | 任意时刻至少 N-1 台在服务 |
| CLB 影响 | 所有后端同时不健康→连接堆积 | 始终有健康后端→无连接堆积 |
滚动重启顺序:跳板机(权重 5,影响最小)→ 竞价实例逐台。每台重启后最多等待 20 秒确认健康检查通过,才继续下一台。
Phase 2: restart LOCAL(w=5) → wait healthy → restart 172.17.0.9(w=10) → wait healthy → restart 172.17.0.15(w=10) → wait healthy
Result: === All deployments successful ===
附录:CloudQ 完整分析报告
以下为 CloudQ 针对本次 CLB 告警返回的完整原始分析报告。
SH-WEB CLB 活跃连接数告警 — 深度分析报告
查询范围:上海地域 lb-iwh0o149(clb-deploy-ehz5w467),时间:23:42 ~ 00:18(UTC+8)
连接监控数据
| 监听器 | 活跃连接数变化 | 并发连接利用率 | 状态 |
|---|---|---|---|
| HTTP 80 | 极低(0~1) | 正常 | 无异常 |
| HTTPS 443 | 5,734 → 47,000+(持续攀升) | ~39% → 100%+(持续超限) | 严重异常 |
根因定位
问题根源:VM-0-9-tencentos 节点上的 3000 端口应用服务持续异常
日志中全量错误均指向同一模式,且当前仍在持续发生:
client: 172.17.0.7 (CLB VIP)
request: "GET /health HTTP/1.1"
upstream: "http://127.0.0.1:3000/health"
host: tsa-lab.cn
时间:23:42 / 23:43 / 23:48 / 23:51 / 23:54 / 23:58 ... 持续中
[error] 41260#41260: *5585523 recv() failed (104: Connection reset by peer)
upstream: "http://127.0.0.1:3000/health"
两种错误类型交替出现:
upstream prematurely closed connection— 3000 端口进程存在但提前断开连接(进程在处理过程中崩溃/重启)recv() failed (104: Connection reset by peer)— 3000 端口进程直接重置连接(进程崩溃后 TCP 被 OS 强制关闭)
CLB 健康检查与连接堆积的恶性循环
↓
3000 端口服务异常 → 返回连接重置/断开
↓
CLB 判定 RS 异常 → 持续发起重试健康检查(间隔极短)
↓
每次失败的健康检查连接未被及时释放 → CLB 连接持续累积
↓
443 端口活跃连接数 5734 → 47000+,利用率突破 100%
当前 RS 健康状态已恢复 Alive,但 CLB 活跃连接数告警仍持续,说明历史积累的半开连接尚未完全释放,或 3000 端口服务仍处于不稳定状态(周期性崩溃)。
处置建议
立即处理(降低告警):
- 登录 VM-0-9-tencentos,排查 3000 端口进程状态和崩溃日志
- 重启 3000 端口应用服务,确保服务稳定响应 /health
- 调整 CLB 健康检查配置:间隔从 5s → 15~30s,不健康阈值 3 次,超时 5s
中期优化(防复发):
- Nginx upstream 配置 keepalive_timeout 和 keepalive_requests 保护
- /health 接口进程守护:使用 PM2 或 systemd Restart=always,崩溃后自动重启
- CLB 连接超时:对长时间未完成连接设置合理超时(60~120s),自动清理半开连接
- Nginx access.log 结构化 JSON 接入 CLS,便于后续 SQL 分析 499/502/504 错误比例
总结
| 维度 | 结论 |
|---|---|
| 告警根因 | VM-0-9-tencentos 上 3000 端口服务异常,CLB 健康检查失败导致连接堆积 |
| 影响范围 | HTTPS 443 端口,活跃连接超限(>47,000);HTTP 80 不受影响 |
| 当前状态 | RS 健康已恢复,但连接堆积尚未消退,告警仍持续 |
| 核心操作 | 立即检查并重启 3000 端口服务 + 调整 CLB 健康检查配置 |