Spring Boot 优雅停机配置详解(含 Docker / Docker Swarm)
Spring Boot 优雅停机配置详解(含 Docker / Docker Swarm)
一、配置说明
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
或者 application.properties 格式:
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=30s
| 配置项 | 作用 |
|---|---|
server.shutdown=graceful | 开启优雅停机,让应用在停止时,不再接收新请求,新请求被gateway分配到集群其他实例上,本实例等待正在处理的请求完成后重启 |
spring.lifecycle.timeout-per-shutdown-phase=30s | 设置每个停机阶段的超时时间上限,默认就是 30s |
二、核心机制
spring.lifecycle.timeout-per-shutdown-phase=30s 的含义:
- 30s 是硬时限(Hard Deadline):最多等待 30 秒
- 提前完成则立即继续:如果所有请求在 10 秒内处理完成,不会傻等剩余的 20 秒,会立即继续关闭流程
- 超时强制终止:如果 30 秒到了还有未完成的请求,Spring 会强制终止这些请求,然后继续关闭应用
日志示例
正常完成:
INFO o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete in 10s
超时强制终止:
INFO o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown timed out after 30s. Active requests: 3
三、IDEA 本地调试效果
注意:本地调试时,如果使用强制停止按钮,优雅停机配置不会生效。
本地验证方法
编写一个慢请求接口:
@RestController
public class TestController {
@GetMapping("/slow")
public String slow() throws InterruptedException {
Thread.sleep(10000); // 10秒慢请求
return "done";
}
}
- 请求
http://localhost:8080/slow - 立即在 IDEA 中点击红色停止按钮
- 观察日志 —— 加了配置会等待请求完成,没加会立即中断
四、各版本默认值变化
| Spring Boot 版本 | server.shutdown 默认值 | 是否需要配置启用优雅停机? |
|---|---|---|
| 2.3.0 至 3.3.x | immediate | 需要。手动配置 server.shutdown=graceful |
| 3.4.0 及之后(含 4.0) | graceful | 不需要。此功能已默认启用 |
重要:优雅停机功能从 Spring Boot 2.3.0 开始引入,但默认开启是从 Spring Boot 3.4.0 版本开始的。
五、Docker 环境配置
5.1 Docker 容器的停止信号
Docker 容器默认使用 SIGTERM 信号来停止容器。Spring Boot 应用会捕获 SIGTERM 信号并触发优雅停机流程。
# 停止容器(默认发送 SIGTERM)
docker stop <container_name>
# 强制停止(发送 SIGKILL,优雅停机不会生效)
docker kill <container_name>
5.2 Dockerfile 最佳实践
FROM openjdk:17-jdk-slim
# 使用 JAR 包方式
COPY target/app.jar /app.jar
# 关键:使用 exec 形式启动,确保应用能正确接收 SIGTERM 信号
ENTRYPOINT ["java", "-jar", "/app.jar"]
# 或者使用完整 JVM 参数(推荐)
ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-XX:MaxRAMPercentage=75.0", "-jar", "/app.jar"]
重要:
ENTRYPOINT必须使用 exec 形式(中括号方式),而不能使用 shell 形式。shell 形式不会直接转发信号给 Java 进程。
# ❌ 错误写法:shell 形式,信号不会被转发
ENTRYPOINT java -jar /app.jar
# ✅ 正确写法:exec 形式,信号正确转发
ENTRYPOINT ["java", "-jar", "/app.jar"]
5.3 docker-compose 配置
version: '3.8'
services:
my-app:
image: my-app:latest
ports:
- "8080:8080"
stop_grace_period: 45s # 必须大于 spring.lifecycle.timeout-per-shutdown-phase
restart: always
environment:
- SERVER_SHUTDOWN=graceful
- SPRING_LIFECYCLE_TIMEOUT-PER-SHUTDOWN-PHASE=30s
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
5.4 时间参数关系图(Docker)
六、Docker Swarm 环境配置
6.1 Swarm 服务的优雅停机
Docker Swarm 在滚动更新或服务缩容时,会按照以下流程操作:
- 将旧容器从负载均衡中摘除(不再接收新请求)
- 发送
SIGTERM信号给容器 - 等待容器自行退出
6.2 docker stack deploy 配置
version: '3.8'
services:
my-app:
image: my-app:latest
ports:
- target: 8080
published: 8080
mode: host
stop_grace_period: 45s
restart_policy:
condition: any
delay: 5s
max_attempts: 3
window: 120s
update_config:
parallelism: 1 # 每次更新 1 个副本
delay: 10s # 更新间隔
failure_action: rollback
monitor: 30s
max_failure_ratio: 0.3
order: start-first # 先启动新容器再停止旧容器
environment:
- SERVER_SHUTDOWN=graceful
- SPRING_LIFECYCLE_TIMEOUT-PER-SHUTDOWN-PHASE=30s
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
restart_policy:
condition: any
6.3 Swarm 滚动更新流程
1. Swarm Manager 调度新容器启动
↓
2. 新容器通过健康检查后,开始接收流量
↓
3. Swarm 将旧容器从 routing mesh 中摘除
↓
4. 旧容器收到 SIGTERM 信号,触发优雅停机
↓
5. 等待 30s(Spring timeout)
├── 请求完成 → 正常退出
└── 超时未完成 → 强制终止
↓
6. 如果 45s(stop_grace_period)后旧容器仍未退出
→ Swarm 发送 SIGKILL 强制杀死
↓
7. 继续更新下一个副本
6.4 Swarm 关键配置参数说明
| 参数 | 建议值 | 说明 |
|---|---|---|
stop_grace_period | 45s - 60s | 必须 > spring.lifecycle.timeout-per-shutdown-phase |
update_config.parallelism | 1 | 每次更新 1 个副本,确保服务可用性 |
update_config.delay | 10s | 更新间隔,给新容器足够时间启动 |
update_config.order | start-first | 先启动新容器再停旧容器,实现零停机 |
healthcheck.start_period | 30s | 给应用足够的启动时间,避免过早检查失败 |
七、生产环境推荐配置汇总
7.1 时间参数配置
| 环境 | Spring timeout | Docker/Swarm stop_grace_period | 说明 |
|---|---|---|---|
| 一般 Web 应用 | 30s(默认) | 45s | 留 15s 缓冲 |
| 有长任务 | 60s - 120s | 90s - 150s | 给慢请求更多时间 |
| 高并发/敏感 | 15s - 20s | 30s | 快速失败,让流量切到其他实例 |
7.2 完整配置清单
application.yml:
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
Dockerfile:
FROM openjdk:17-jdk-slim
COPY target/app.jar /app.jar
ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-XX:MaxRAMPercentage=75.0", "-jar", "/app.jar"]
docker-compose.yml:
services:
my-app:
image: my-app:latest
stop_grace_period: 45s
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
Swarm 服务配置(docker-stack.yml):
services:
my-app:
image: my-app:latest
stop_grace_period: 45s
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
failure_action: rollback
monitor: 30s
八、常见问题排查
8.1 优雅停机不生效
-
检查
ENTRYPOINT是否使用 exec 形式:- 使用
["java", "-jar"]✅ - 不要使用
java -jar❌
- 使用
-
检查
server.shutdown是否配置为graceful(Spring Boot 3.4.0 之前) -
检查是否使用了强制停止命令:
docker kill不会触发优雅停机- 应使用
docker stop或docker service update
8.2 容器被提前强制杀死
# 查看容器日志,确认是否为超时被 kill
docker logs <container_name> | grep -i "shutdown\|timeout\|kill"
# 检查 Docker stop_grace_period 是否小于 Spring timeout
docker inspect <container_name> | grep -i "stopgraceperiod"
解决:增大 stop_grace_period,确保大于 spring.lifecycle.timeout-per-shutdown-phase。
8.3 滚动更新期间出现 5xx 错误
- 增加
healthcheck.start_period,给新容器足够时间启动 - 增加
update_config.delay,让流量有足够时间切换 - 检查 Spring Boot 的
management.server.port是否独立,避免健康检查端口与应用端口冲突
九、完整停机流程示意图
十、总结
| 关键点 | 说明 |
|---|---|
| Spring timeout | 最多等待请求完成的时限(默认 30s) |
| Docker stop_grace_period | Docker 等待容器退出的总时限,必须 > Spring timeout |
| 信号传递 | 必须使用 exec 形式的 ENTRYPOINT,确保 SIGTERM 正确传递 |
| 滚动更新 | Swarm 的 start-first 策略可实现零停机部署 |
| 健康检查 | 配置合理的健康检查,确保新容器正常后才接入流量 |
| 超时关系 | K8s terminationGracePeriodSeconds > Docker stop_grace_period > Spring timeout |
一句话总结:30s 是 Spring 等待请求完成的"硬上限";Docker/Swarm 的
stop_grace_period是容器等待退出的"总上限",必须大于 Spring 的 timeout,并留出 10-15s 的缓冲时间,同时确保 ENTRYPOINT 使用 exec 形式传递信号,才能实现真正的优雅停机和无损发布。
更多推荐

所有评论(0)