1. 为什么我们需要关注优雅停机与健康检查?
春节假期对软件系统来说是个特殊的考验期。当大多数开发团队进入休假模式,线上系统却要面临流量波动、运维响应延迟等挑战。去年春节我就吃过亏——某个核心服务在假期首日凌晨触发自动扩容,结果因为不规范的停机流程导致数据不一致,花了整个假期来修复。
优雅停机(Graceful Shutdown)和健康检查(Health Check)正是解决这类问题的银弹。前者确保服务在终止前完成现有请求、释放资源,后者则持续监控服务状态,避免将流量导向不健康的实例。这两项能力构成了系统稳定性的基石,尤其在无人值守的长假期间更为关键。
2. 优雅停机的实现原理与落地实践
2.1 操作系统信号处理机制
当我们在Kubernetes中执行kubectl delete pod时,实际触发的是SIGTERM信号。这个15号信号给了进程一个"缓冲期",通常30秒后仍未停止才会发送SIGKILL强制终止。以下是一个Go语言的信号处理示例:
func main() { stopChan := make(chan os.Signal, 1) signal.Notify(stopChan, syscall.SIGTERM, syscall.SIGINT) go func() { <-stopChan fmt.Println("收到终止信号,开始清理...") // 1. 停止接收新请求 // 2. 完成进行中的任务 // 3. 关闭数据库连接 // 4. 其他资源释放 os.Exit(0) }() // 正常业务逻辑... }2.2 分布式场景下的连锁反应
在微服务架构中,不规范的停机可能导致雪崩效应。我曾遇到一个典型案例:服务A突然下线,导致服务B的连接池积压,进而引发服务C的超时。正确的做法应该包括:
- 先从负载均衡摘除节点
- 等待活跃连接完成(Nginx默认10秒)
- 发送SIGTERM信号
- 强制终止前记录最后状态
重要提示:Spring Boot 2.3+版本内置优雅停机支持,通过
server.shutdown=graceful启用,但需要注意与spring.jpa.open-in-view的兼容性问题。
3. 健康检查的维度设计与实现
3.1 存活探针 vs 就绪探针
Kubernetes的两种探针经常被混淆,实际差异显著:
| 探针类型 | 检查目标 | 失败后果 | 典型检查内容 |
|---|---|---|---|
| 存活探针 | 进程是否正常运行 | 重启容器 | TCP端口连通性、/healthz接口 |
| 就绪探针 | 是否准备好接收流量 | 从Service端点移除 | 依赖服务状态、线程池饱和度 |
3.2 分级健康检查策略
在电商系统实践中,我推荐三级检查机制:
- 基础层:5秒间隔的HTTP 200检查
- 依赖层:验证数据库、缓存等关键依赖
- 业务层:核心链路接口模拟调用(如创建订单)
# Kubernetes配置示例 livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 5 readinessProbe: exec: command: - "/bin/sh" - "-c" - "curl -s http://localhost:8080/ready | grep -q 'OK'" timeoutSeconds: 14. 春节特别场景下的增强方案
4.1 流量突降时的资源回收
春节期间往往出现流量"断崖式"下跌。某社交App的实践值得参考:
- 00:00-06:00自动缩容到30%实例
- 缩容前执行双重确认:
- 检查最近5分钟错误率<0.1%
- 确保至少2个健康实例保留
4.2 值班响应机制设计
即使有自动化措施,仍需准备人工介入方案。我们的oncall手册包含:
- 关键指标速查表(错误率、延迟、队列深度)
- 分级响应流程(电话->语音信箱->短信轰炸)
- 预案执行checklist(含截图和复制粘贴命令)
5. 常见陷阱与诊断技巧
5.1 优雅停机的典型反模式
- 资源泄漏:未关闭的文件描述符会持续占用内存
- 请求中断:Nginx默认10秒等待可能不足
- 状态不一致:数据库事务未提交即终止
诊断命令推荐:
# 查看进程状态 ps aux | grep [服务名] # 检查未关闭的文件描述符 lsof -p [PID] # 监控请求处理情况 netstat -tulnp | grep [端口]5.2 健康检查的误判场景
某次事故让我记忆犹新:健康检查接口返回200,但实际业务已阻塞。后来我们增加了以下验证:
- 检查线程池使用率(超过90%标记不健康)
- 验证测试订单能否创建成功
- 监控内部队列积压情况
6. 设计阶段评审要点
参考最新的热词趋势,在系统设计评审时建议关注:
停机流程文档:
- 信号处理时序图
- 资源释放checklist
- 超时时间配置依据
健康检查模板:
## 健康检查规范 - [ ] 基础存活检查(端口/进程) - [ ] 依赖服务连通性 - [ ] 业务语义验证 - [ ] 压力状态检测(CPU/内存)应急预案:
- 手动摘除流量的kubectl命令
- 强制终止的权限控制
- 状态恢复的验证步骤
在实现这些机制时,我发现最容易被忽视的是时间参数的合理性。比如某个服务关闭数据库连接需要8秒,但等待期只配置了5秒,这会导致部分连接强制中断。经过多次压测,我们总结出一个公式:优雅停机超时应 ≥ (最长事务时间 × 2) + 缓冲时间(3秒)。