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 配置示例 来演示优雅关闭的实际效果。是否需要?

相关推荐
小羊在睡觉4 小时前
golang定时器
开发语言·后端·golang
pengzhuofan4 小时前
第10章 Maven
java·maven
用户21411832636024 小时前
手把手教你在魔搭跑通 DeepSeek-OCR!光学压缩 + MoE 解码,97% 精度还省 10-20 倍 token
后端
追逐时光者4 小时前
一个基于 .NET 开源、功能强大的分布式微服务开发框架
后端·.net
百锦再5 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说5 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多5 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再5 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
间彧5 小时前
Java双亲委派模型的具体实现原理是什么?
后端