SpringBoot应用优雅停机的3种标准方案
线上发布、重启服务时,你是不是直接 kill -9 一把梭?
后果往往是:
- 正在处理的请求直接中断,前端报错 502;
- 事务没提交,导致数据不一致;
- 线程池、连接池暴力关闭,资源泄漏;
- MQ 消息消费一半,出现重复/丢失。
所谓优雅停机(Graceful Shutdown),就是让应用在关闭前:
- 停止接收新请求;
- 把正在处理的请求执行完;
- 释放线程池、连接池、MQ 消费者等资源;
- 最后再安全退出。
今天讲清楚 SpringBoot 优雅停机的 3 种标准方案,生产直接抄配置。
一、什么是优雅停机?
简单说 4 件事:
- 不再接收新的 HTTP 请求 / 新消息
- 等待正在执行的业务执行完毕
- 自动关闭线程池、数据库连接、Redis 连接
- 安全退出 JVM,不丢数据、不中断事务
SpringBoot 2.3+ 已经内置支持,不用自己写复杂钩子。
二、方式1:配置文件开启内置优雅停机
1)application.yml 配置
server: # 优雅停机最大等待时间(单位为秒) shutdown: graceful spring: lifecycle: # 所有 Bean 关闭的最大等待时间 timeout-per-shutdown-phase: 30s
server.shutdown: graceful
:开启 Web 容器优雅停机
timeout-per-shutdown-phase: 30s
:给 30 秒缓冲时间
2)支持的容器
- Tomcat
- Jetty
- Undertow
全都通用,不用改代码。
三、方式2:Actuator 优雅停机
适合:发布平台、脚本自动化重启。
1)引入依赖
<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-actuatorartifactId> <dependency>
2)开启 shutdown 端点
management:
endpoints:
web:
exposure:
include: shutdown,health
endpoint:
shutdown:
enabled:true3)远程调用关闭
curl-X POST http://localhost:8080/actuator/shutdown
应用会优雅停机,不是暴力杀进程。
4)生产安全提醒
- 一定要配合 Spring Security 权限控制
- 只对内网开放,不要暴露到公网
- 不要在生产随意打开
/actuator/shutdown
四、方式3:kill + 信号优雅停机
最常用、最推荐的生产方式。
正确命令
kill PID # 或者 kill-15 PID
绝对禁止
kill-9 PID # 暴力杀,不优雅,会丢数据!
SpringBoot 会捕获 SIGTERM 信号,自动执行优雅停机流程。
五、如何保证自己的业务也“优雅”?
如果你有:
- 自定义线程池
- MQ 消费者
- 定时任务
- socket 长连接
需要加一个关闭钩子,保证资源释放。
@Component
publicclassAppShutdownHook{
@PreDestroy
publicvoiddestroy(){
// 关闭线程池、消费者、连接等
System.out.println("应用正在优雅关闭:清理自定义资源");
}
}或者实现 DisposableBean。
六、优雅停机完整流程
- 收到关闭信号(kill / actuator / 控制台停止)
- Web 容器不再接受新请求
- 等待正在执行的 HTTP 请求完成
- 关闭 Spring 容器,执行
@PreDestroy - 关闭线程池、数据源、MQ 客户端
- JVM 安全退出
整个过程在 timeout 时间内完成。
七、生产最佳实践
- 一律用 kill PID,禁止 kill -9
- 配置优雅停机超时 20~30s
- 发布脚本先切流量,再停机
- 自定义线程池/消费者必须加关闭钩子
- 用 Actuator 做自动化发布时开启权限
- 日志里观察停机日志,确认是 graceful 关闭
八、常见坑
超时时间太短
长接口、大事务没执行完就被关闭 → 加大 timeout
用 kill -9
等于直接拔电源,任何优雅机制都失效
自定义线程池没关闭
应用关了,线程还在跑 → 用 @PreDestroy 关闭
Actuator 未授权暴露 shutdown
被人恶意调用,直接关服务
到此这篇关于SpringBoot应用优雅停机的3种标准方案的文章就介绍到这了,更多相关SpringBoot优雅停机方案内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
springboot+thymeleaf+shiro标签的实例
这篇文章主要介绍了springboot+thymeleaf+shiro标签的实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-01-01
Java I/O (Input/Output)文件字节流举例详解
Java的输入输出流(IO)是用于与外部设备(如文件、网络连接等)进行数据交互的机制,下面这篇文章主要给大家介绍了关于Java I/O (Input/Output)文件字节流的相关资料,需要的朋友可以参考下2024-08-08
SpringBoot+mybatis+thymeleaf实现登录功能示例
这篇文章主要介绍了SpringBoot+mybatis+thymeleaf实现登录功能示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-07-07
Java8 将一个List<T>转为Map<String,T>的操作
这篇文章主要介绍了Java8 将一个List<T>转为Map<String, T>的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2021-02-02


最新评论