优雅关闭(Graceful Shutdown)
服务重启、发布、缩容时,如果没有优雅关闭机制,正在处理的请求会被强制中断,轻则返回错误,重则数据不一致。
你有没有注意到过这种情况:用户下单时页面突然报错,但后台订单其实已经创建成功了。这就是没有优雅关闭的典型症状——请求被强制中断,用户以为失败了,但实际上后端已经处理完成。
为什么需要优雅关闭
先看一个没有优雅关闭的问题场景:
问题:
- 事务未提交,订单丢失
- 库存已扣减但订单未创建,数据不一致
- 用户体验差,不知道请求是否成功
优雅关闭的流程
Spring Boot 优雅关闭
基础配置
application.yml
配置含义
代码层面配合
GracefulShutdownHandler.java
Tomcat 特殊处理
Tomcat 的线程池处理请求时,需要特殊处理:
TomcatGracefulShutdown.java
Kubernetes 优雅关闭配置
terminationGracePeriodSeconds
pod-graceful-shutdown.yaml
流程:
- K8s 发送 SIGTERM(0 秒)
- Pod 开始优雅关闭
- 等待最多
terminationGracePeriodSeconds秒 - 如果还未退出,发送 SIGKILL
preStop Hook
preStop Hook 在发送 SIGTERM 之前执行,常用于等待负载均衡器更新:
prestop-hook.yaml
为什么需要 preStop Hook?
preStop Hook 的作用:在发送 SIGTERM 之前,先等待负载均衡器更新。
完整配置示例
complete-graceful-shutdown.yaml
关闭流程时序
常见问题与解决
问题一:线程池任务无法取消
TaskCancellation.java]
问题二:Kafka 消费者关闭
KafkaGracefulShutdown.java]
问题三:数据库连接池关闭顺序
DatabaseGracefulShutdown.java]
监控优雅关闭
graceful-shutdown-metrics.yaml]
质量判断标准
一篇「优雅关闭」的文章是否达标,要看它是否回答了:
- ✅ 为什么需要优雅关闭(没有优雅关闭会怎样)?
- ✅ 完整的优雅关闭流程是什么?
- ✅ Spring Boot 如何配置?
- ✅ K8s 如何配置(terminationGracePeriodSeconds、preStop Hook)?
- ✅ 常见问题如何处理(线程池、Kafka、数据库)?
- ❌ 只有配置,没有时序图和问题分析——不达标
本章总结
核心要点:
- 优雅关闭防止请求中断和数据不一致:没有优雅关闭会导致事务未提交、订单丢失
- K8s 发送 SIGTERM 触发优雅关闭:应用需要在收到后停止接收新请求并完成处理中的任务
- preStop Hook 等待负载均衡器更新:防止新请求被路由到正在关闭的 Pod
- terminationGracePeriodSeconds 控制总时间:超过后强制退出
- 关闭顺序很重要:先停入口,再停处理,最后停资源(数据库、消息队列)