【SpringBoot实战】优雅关闭服务
文章目录
- 一、什么是优雅关闭?
- 二、优雅关闭的核心步骤
- 三、SpringBoot优雅关闭实现
- 四、关键注意事项
- 1. 超时时间必须配置
- 2. 信号支持局限性
- 3. 特殊请求处理
- 五、底层实现原理
- 六、总结
一、什么是优雅关闭?
优雅关闭(Graceful Shutdown) 是指服务在关闭或重启时,先完成所有正在处理的请求,再安全终止进程的机制。这种机制能有效避免以下问题:
- 用户请求突然中断导致的客户端报错
- 数据库事务执行到一半被强制终止
- 负载均衡将流量导向正在关闭的节点
下面来看典型的架构场景:
当对服务实例进行滚动更新时,若直接终止实例,正在处理的请求将失败。
二、优雅关闭的核心步骤
- 流量摘除
CI/CD系统将目标节点从负载均衡(如Nginx)的后端服务器组中移除 - 接收终止信号
进程接收到操作系统发送的终止信号(如SIGTERM) - 停止接收新请求
服务立即关闭端口监听,拒绝新请求进入 - 等待既有请求完成
服务等待所有正在处理的请求完成(包括长任务) - 进程安全退出
资源清理后终止进程
三、SpringBoot优雅关闭实现
自 SpringBoot 2.3.0 起官方内置优雅关闭支持:
点击访问
翻译过来这句话的意思就是:
将 Web 服务的优雅关闭集成到应用程序上下文(ApplicationContext)的生命周期处理中
配置方式(application.yml)
server:shutdown: graceful # 启用优雅关闭(支持Tomcat/Jetty/Undertow等Web容器)spring:lifecycle:timeout-per-shutdown-phase: 60s # 最大等待时间(超时后强制关闭),生产环境必须设置!
四、关键注意事项
1. 超时时间必须配置
- 为什么需要超时?
防止因某些请求阻塞(如慢SQL、死循环)导致实例永远无法关闭 - 推荐设置
根据业务最长处理时间设定(通常 ≥ 最大请求超时时间 × 2)
2. 信号支持局限性
信号名称 | 是否触发优雅关闭 | 说明 |
---|---|---|
SIGTERM | ✅ | kill -15(默认推荐) |
SIGINT | ✅ | Ctrl+C 或 kill -2 |
SIGKILL | ❌ | kill -9 立即强制终止 |
📌 生产环境应使用 SIGTERM 触发关闭
3. 特殊请求处理
- 长轮询/WebSocket连接:需要业务层实现连接关闭通知
- 批处理任务:建议拆分可中断任务,或记录任务状态
五、底层实现原理
SpringBoot 通过注册 Shutdown Hook 实现:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {// 1. 关闭ServerSocket停止接收请求// 2. 检查活动请求计数器// 3. 等待计数器归零或超时
}));
六、总结
通过 SpringBoot 原生支持的优雅关闭机制,配合基础设施的流量控制,可实现服务的零中断发布。关键点在于:
- 正确配置 server.shutdown=graceful + 超时时间
- 使用 SIGTERM 而非 SIGKILL 终止进程
- 基础设施层保证流量摘除先于进程终止
生产环境发布效果对比:
未启用优雅关闭:发布期间错误率飙升
启用后:错误率曲线保持平稳 🚀