Spring Boot优雅关闭全解析

以下这段文字来自 Spring Boot 官方文档 (5.8 节"Graceful shutdown"),讲的是 如何在 Spring Boot 应用中启用"优雅关闭"(Graceful Shutdown)功能。下面我们逐段解析,并用通俗易懂的方式解释其含义和应用场景。


🌟 什么是"优雅关闭"?

想象一下:你的 Web 服务正在处理用户请求,比如用户正在下单、上传文件、查询数据。这时,你决定关闭服务(比如部署新版本)。如果直接"粗暴"地关掉服务,那些正在进行的请求就会被中断,导致数据不一致、用户体验差等问题。

优雅关闭 就是:在关闭服务时,先"告诉"服务器:"不要再接收新请求了,但已经进来的请求请让我处理完,等它们都完成了,再真正关闭。"

这样可以避免请求丢失或中途失败,提升系统的稳定性和用户体验。


🔍 原文逐句解读

1.

Graceful shutdown is supported with all four embedded web servers (Jetty, Reactor Netty, Tomcat, and Undertow) and with both reactive and Servlet-based web applications.

✅ 含义:

  • Spring Boot 支持四种内嵌 Web 服务器:Jetty、Reactor Netty、Tomcat、Undertow
  • 无论是基于 响应式编程 (如 WebFlux)还是传统的 Servlet 模型(如 Spring MVC),都支持优雅关闭。

👉 也就是说:无论你用哪种技术栈,都能使用这个功能。


2.

It occurs as part of closing the application context and is performed in the earliest phase of stopping SmartLifecycle beans.

✅ 含义:

  • 优雅关闭是 Spring 应用上下文(ApplicationContext)关闭过程的一部分。
  • 它发生在 SmartLifecycle 组件停止的最早阶段

📌 补充知识:

  • SmartLifecycle 是 Spring 提供的一个接口,用于控制 Bean 的启动和停止顺序。
  • 把优雅关闭放在"最早阶段"意味着:一旦开始关,就立刻进入"拒绝新请求"的状态,防止新的请求进来干扰关闭流程。

3.

This stop processing uses a timeout which provides a grace period during which existing requests will be allowed to complete but no new requests will be permitted.

✅ 含义:

  • 有一个 超时时间(timeout),叫做"宽限期"(grace period)。
  • 在这段时间内:
    • ✅ 已经到达的请求:允许继续执行,直到完成。
    • ❌ 新的请求:不允许再进来。

📌 举例:

如果你设置 timeout = 30s,那么系统最多会等 30 秒来让正在进行的请求完成。超过 30 秒还没完成的请求,会被强制终止。


4.

The exact way in which new requests are not permitted varies depending on the web server that is being used. Jetty, Reactor Netty, and Tomcat will stop accepting requests at the network layer. Undertow will accept requests but respond immediately with a service unavailable (503) response.

✅ 含义:不同服务器处理"拒绝新请求"的方式不一样:

服务器 如何拒绝新请求
Jetty / Reactor Netty / Tomcat 直接在网络层拒绝连接,客户端会收到连接失败(如 Connection refused)
Undertow 仍然接受连接,但立即返回 HTTP 状态码 503 Service Unavailable

📌 区别:

  • 前三者更"强硬":直接不让连接进来。
  • Undertow 更"友好":告诉客户端"我现在忙,不能服务你",适合某些负载均衡场景。

5.

Graceful shutdown with Tomcat requires Tomcat 9.0.33 or later.

✅ 含义:

  • 如果你用的是 Tomcat ,必须使用 9.0.33 或更高版本 才支持优雅关闭。
  • 老版本不支持,即使配置了也不会生效。

⚠️ 注意:Spring Boot 2.3+ 才引入此功能,且默认内嵌的 Tomcat 版本需满足要求。


6.

To enable graceful shutdown, configure the server.shutdown property, as shown in the following example:

server.shutdown=graceful

✅ 含义:

这是开启优雅关闭的关键配置!

application.ymlapplication.properties 中添加:

yaml 复制代码
# application.yml
server:
  shutdown: graceful

properties 复制代码
# application.properties
server.shutdown=graceful

👉 默认值是 immediate(立即关闭),设为 graceful 才启用优雅关闭。


7.

To configure the timeout period, configure the spring.lifecycle.timeout-per-shutdown-phase property, as shown in the following example:

spring.lifecycle.timeout-per-shutdown-phase=20s

✅ 含义:

设置"宽限期"------即最多等多久让现有请求完成。

例如:

yaml 复制代码
spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s

表示:最多等待 30 秒。

⚠️ 注意:

  • 如果某个请求跑了 40 秒还没完,那它会在 30 秒时被强制中断。
  • 这个超时是全局的,适用于所有需要优雅停止的组件。

8.

Using graceful shutdown with your IDE may not work properly if it does not send a proper SIGTERM signal. Refer to the documentation of your IDE for more details.

✅ 含义:

  • 优雅关闭依赖操作系统发送的 SIGTERM 信号(Linux/Unix 下的标准终止信号)。
  • 但很多 IDE(如 IntelliJ IDEA、Eclipse) 在点击"停止按钮"时,并不会发送 SIGTERM,而是直接杀进程(相当于 kill -9),这就跳过了优雅关闭流程!

👉 结果:配置了也没用,请求照样被中断。

✅ 解决方案:

  • 在生产环境使用命令行启动(如 java -jar app.jar),并通过 kill <pid> 发送 SIGTERM。
  • 或者使用容器化部署(如 Docker),配合 stop-signal: SIGTERM 和合理的 stopTimeout

✅ 总结:如何正确使用优雅关闭?

第一步:修改配置文件
yaml 复制代码
# application.yml
server:
  shutdown: graceful    # 开启优雅关闭

spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s   # 最多等待30秒
第二步:确保环境支持
  • 使用 Tomcat ≥ 9.0.33(Spring Boot 2.3+ 默认满足)
  • 部署方式要能发送 SIGTERM 信号(避免 kill -9 或 IDE 强制停止)
第三步:测试验证

你可以通过以下方式测试:

  1. 启动应用
  2. 发起一个长请求(比如 sleep 10 秒的接口)
  3. 在请求执行过程中,执行 kill <pid>(而不是 kill -9
  4. 观察日志:是否等待请求完成后才关闭?

💡 适用场景

场景 是否推荐使用优雅关闭
生产环境部署/滚动更新 ✅ 强烈推荐
使用 Kubernetes / Docker ✅ 推荐,配合合理的 terminationGracePeriodSeconds
本地开发调试 ⚠️ 可能无效(IDE 不发 SIGTERM)
高并发交易系统 ✅ 必须使用,防止订单丢失

📌 小贴士

  • 优雅关闭 ≠ 永远不中断请求,它只是给了一个"缓冲期"。
  • 超时后仍未完成的请求,仍会被中断。
  • 建议结合监控和日志,观察关闭期间的请求情况。

如有需要,我可以提供一个 Spring Boot 示例项目Docker + Kubernetes 配置示例 来演示优雅关闭的实际效果。是否需要?

相关推荐
guestsun2 小时前
SpringBoot七大事务失效场景分析
java·spring boot·mybatis
毕设源码-邱学长7 小时前
【开题答辩全过程】以 基于Java的学校住宿管理系统的设计与实现为例,包含答辩的问题和答案
java·开发语言
兑生9 小时前
【灵神题单·贪心】1481. 不同整数的最少数目 | 频率排序贪心 | Java
java·开发语言
daidaidaiyu9 小时前
一文学习 Spring 声明式事务源码全流程总结
java·spring
颜酱9 小时前
DFS 岛屿系列题全解析
javascript·后端·算法
零雲10 小时前
java面试:了解抽象类与接口么?讲一讲它们的区别
java·开发语言·面试
小码哥_常10 小时前
Java后端定时任务抉择:@Scheduled、Quartz、XXL - Job终极对决
后端
uzong10 小时前
Skill 被广泛应用,到底什么是 Skill,今天详细介绍一下
人工智能·后端·面试
小码哥_常11 小时前
Kafka平替!SpringBoot+Redis Stream+消费组打造极致消息队列
后端
IT_陈寒12 小时前
Redis缓存击穿:3个鲜为人知的防御策略,90%开发者都忽略了!
前端·人工智能·后端