什么是“优雅关闭”(Graceful Shutdown)
1. 什么是“优雅关闭”(Graceful Shutdown)
优雅关闭指的是:在系统或服务停止时,不立刻粗暴地中断进程,而是有秩序地完成“善后工作”,再安全退出。
它的核心目标只有一个:不丢数据、不伤用户、不留烂摊子。
可以把它想成餐厅打烊:不再接新客 → 让已入座的客人吃完 → 结账 → 关灯锁门,而不是直接拉闸断电。
1.1 优雅关闭解决的本质问题
- 正在处理的请求怎么办
- 正在写的数据是否会损坏
- 上游/下游是否感知到服务已下线
- 集群整体是否还能保持稳定
2. 没有优雅关闭会发生什么
2.1 对业务的影响
- HTTP 请求直接被中断,用户看到 502 / 504
- 事务未提交,产生脏数据或数据不一致
- 消息消费一半,导致重复消费或消息丢失
2.2 对系统的影响
- 连接未释放(TCP、DB 连接池)
- 文件句柄、锁未释放
- 集群误判为异常宕机,引发级联故障
一句话总结:暴力退出是技术债,优雅关闭是工程素养。
3. 优雅关闭的标准流程
3.1 阶段一:停止接收新请求
- 负载均衡 / Service Mesh / Ingress 摘除流量
- 应用层返回“即将下线”信号
3.2 阶段二:处理完已存在的工作
- 等待正在执行的 HTTP 请求完成
- 等待 Goroutine / Thread / Worker 收尾
- 消费完已拉取的消息
3.3 阶段三:资源释放与状态持久化
- Flush 缓存 / 日志
- 提交或回滚事务
- 关闭 DB、MQ、Redis 连接
3.4 阶段四:进程退出
- 返回 0,告诉系统:我不是“死的”,我是“退役的”
4. 在 Linux / 容器世界里的体现
4.1 信号语义
SIGTERM:请你体面地退出(优雅关闭的起点)SIGKILL:我没耐心了,直接掐死(没有任何清理机会)
4.2 Docker / Kubernetes 的行为
docker stop→ 先发 SIGTERM,再等 timeoutK8s Pod 删除流程:
- Endpoint 下线
- 发送 SIGTERM
- 等
terminationGracePeriodSeconds - 超时才 SIGKILL
5. 典型的优雅关闭架构
sequenceDiagram
participant User
participant LB as LoadBalancer
participant Pod
participant App
User->>LB: 请求
LB->>Pod: 转发请求
Pod->>App: 处理
Note over Pod,App: Pod 被删除
LB-->>Pod: 停止转发新流量
Pod->>App: SIGTERM
App->>App: 等待正在处理的请求
App->>App: 释放资源/Flush
App-->>Pod: 正常退出
6. 不同系统中的“优雅关闭”侧重点
6.1 Web 服务
- 请求不被中断
- KeepAlive 连接平滑关闭
6.2 消息系统(Kafka / RabbitMQ)
- 不再拉新消息
- 已消费消息确认(ACK)
6.3 数据库 / 存储
- Flush WAL / Buffer
- 保证一致性点
7. 一个工程师视角的判断标准
如果一个服务具备以下能力,基本算“合格”:
- 能正确处理 SIGTERM
- 能配置最大优雅关闭时间
- 在关闭期间对用户无明显感知
- 日志中能清晰看到 shutdown 过程