SpringBoot 优雅停机演进:实现原理与最佳实践

SpringBoot 优雅停机演进:实现原理与最佳实践

❃博主首页 :「程序员1970」 ,同名公众号「程序员1970」
☠博主专栏 :<mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关>


微服务和云原生时代,应用的平滑启停是保障系统高可用的关键环节。Spring Boot 在 2.3 版本引入了对内嵌 Web 容器优雅停机的原生支持,改变此前需要手动编码实现局面。

一、什么是“优雅停机”?

优雅停机(Graceful Shutdown) 是指在应用停止过程中:

  1. 立即停止接收新请求
  2. 允许已进入的请求继续处理完成
  3. 安全释放资源(数据库连接、线程池、缓存等);
  4. 避免客户端收到 5xx 错误或连接中断

若未实现优雅停机,在滚动更新、缩容或重启时,极易出现如下典型异常:

ERROR ... - Error creating bean with name 'orderController': Singleton bean creation not allowed while singletons of this factory are in destruction org.springframework.beans.factory.BeanCreationNotAllowedException: ... 

异常表明:Spring 容器正在销毁,但仍有请求试图获取 Controller Bean —— 这正是停机流程设计不当的直接体现。


二、核心组件与层级关系

要理解停机流程,需先厘清以下组件的包含关系:

JVM └── 内嵌 Web 容器(如 Tomcat) └── Servlet 容器(StandardContext) └── DispatcherServlet(Spring MVC 入口) └── Spring ApplicationContext(IoC 容器) └── 所有 Spring Bean(@Controller, @Service 等) 
  • Web 容器(Tomcat/Jetty/Undertow):负责网络连接与线程调度。
  • Servlet 容器:管理 Servlet、Filter 生命周期。
  • Spring 容器:即 ApplicationContext,管理 Bean 的创建与销毁。
  • Spring Boot不是容器,而是自动集成 Web 容器 + Spring 容器的启动框架。
⚠️ 关键点:Spring 容器运行在 Web 容器内部。停机时,必须协调二者关闭顺序,否则就会出现“Web 容器还在处理请求,但 Spring 容器已拒绝服务”的竞态条件。

三、Spring Boot < 2.3:手动实现的“伪优雅”

在2.3之前,Spring Boot 没有内置优雅停机能力。默认行为是:

  1. 收到 SIGTERM(如 kill -15);
  2. 立即关闭 Spring 容器 → 设置 singletonsCurrentlyInDestruction = true
  3. Web 容器仍在运行,继续 accept 新连接并分配线程;
  4. 若此时有请求进入,DispatcherServlet 尝试通过 getBean("orderController") 获取 Controller;
  5. 因 Spring 容器已标记为“销毁中”,抛出 BeanCreationNotAllowedException

❌ 问题本质:关闭顺序错误

先关 Spring,再关 Web 容器 → 存在危险时间窗口。

🛠️ 开发者workaround

需手动实现以下逻辑:

@ComponentpublicclassGracefulShutdownimplementsTomcatConnectorCustomizer,ApplicationListener<ContextClosedEvent>{privatevolatileConnector connector;@Overridepublicvoidcustomize(Connector connector){this.connector = connector;}@OverridepublicvoidonApplicationEvent(ContextClosedEvent event){ connector.pause();// 停止接收新请求Executor executor = connector.getProtocolHandler().getExecutor();if(executor instanceofThreadPoolExecutor){try{((ThreadPoolExecutor) executor).shutdown();((ThreadPoolExecutor) executor).awaitTermination(30,TimeUnit.SECONDS);}catch(InterruptedException e){Thread.currentThread().interrupt();}}}}

同时需注册到 Tomcat:

@BeanpublicServletWebServerFactoryservletContainer(){TomcatServletWebServerFactory tomcat =newTomcatServletWebServerFactory(); tomcat.addConnectorCustomizers(gracefulShutdown());return tomcat;}
💡 即便如此,仍无法完美处理 HTTP/1.1 keep-alive 连接复用带来的新请求。

四、Spring Boot ≥ 2.3:原生优雅停机

Spring Boot 2.3 引入了 标准化的优雅停机机制,通过两行配置即可启用:

server:shutdown: graceful # 启用优雅停机spring:lifecycle:timeout-per-shutdown-phase: 30s # 等待超时时间

✅ 核心思想:反转关闭顺序 + 流量控制前置

停机流程变为:

  1. Web 容器立即 pause:停止 accept 新连接(Tomcat 调用 connector.pause());
  2. 等待已进入的请求完成:最多等待 timeout-per-shutdown-phase 时间;
  3. 确认无活跃请求后,关闭 Spring 容器:销毁所有 Bean;
  4. 彻底停止 Web 容器线程池

🧠 底层原理

1. SmartLifecycle 控制关闭阶段

Spring Boot 注册了 WebServerGracefulShutdownLifecycle,它实现 SmartLifecycle 接口,并设置:

@OverridepublicintgetPhase(){returnInteger.MAX_VALUE;// 最后启动,最先停止}

确保其 stop() 方法在普通 Bean 销毁之前执行。

2. WebServer 接口标准化

不同内嵌服务器实现统一的 GracefulShutdown 行为:

  • Tomcatpause() + 等待线程池
  • Jetty:停止 acceptor 线程
  • Undertow:返回 503 给新请求
  • Reactor Netty:发送 GOAWAY(HTTP/2)
3. 与 Spring 生命周期深度集成

通过 LifecycleProcessor 协调所有 SmartLifecycle Bean 的关闭顺序,确保 Web 容器优雅关闭完成之后,才触发 ApplicationContext.close()


五、2.3 前后对比总表

维度Spring Boot < 2.3Spring Boot ≥ 2.3
是否内置支持❌ 需手动编码✅ 开箱即用
关闭起点Spring 容器Web 容器
新请求处理继续 accept → 高风险立即拒绝(pause/503)→ 安全
已进入请求可能因 Spring 关闭而失败等待完成(最多 timeout)
典型异常BeanCreationNotAllowedException 高频极少(除非超时)
配置复杂度高(需自定义监听器)低(仅需 YAML)
多容器支持仅限手动适配自动支持 Tomcat/Jetty/Undertow/Netty
K8s 友好度优秀

六、生产环境最佳实践

1. 启用优雅停机(2.3+)

server:shutdown: graceful spring:lifecycle:timeout-per-shutdown-phase: 45s # > 业务最大请求耗时

2. Kubernetes 部署配合 preStop

spec:containers:-name: app lifecycle:preStop:exec:command:["sleep","15"]# 给 LB 时间摘除节点terminationGracePeriodSeconds:60

3. Windows 服务需走 Actuator

management:endpoint:shutdown:enabled:trueendpoints:web:exposure:include:"shutdown"

并通过外部命令触发:

curl-X POST http://localhost:8080/actuator/shutdown 

4. 监控与告警

  • 监控停机期间的 5xx 错误率;
  • 若仍有 BeanCreationNotAllowedException,检查:
    • 超时时间是否足够;
    • LB 摘除延迟;
    • 是否存在长轮询/WebSocket 未处理。

🌟 一句话建议
只要你的Spring Boot 版本 ≥ 2.3,务必启用 server.shutdown=graceful,并配合基础设施实现流量摘除。这能显著提升系统在滚动更新、弹性伸缩场景下的稳定性与用户体验。

关注公众号获取更多技术干货 !

Read more

Z-Image-Turbo镜像推荐:Gradio WebUI免配置快速上手教程

Z-Image-Turbo镜像推荐:Gradio WebUI免配置快速上手教程 你是不是也遇到过这些情况:想试试最新的AI绘画模型,结果卡在环境搭建上——下载权重动辄几十GB、配置CUDA版本让人头大、改配置文件改到怀疑人生?或者好不容易跑起来了,WebUI界面又丑又难用,中文提示词还乱码?别折腾了。今天要介绍的这个镜像,真的做到了“点开即用”。 Z-Image-Turbo不是又一个参数堆砌的玩具模型,而是阿里通义实验室实打实打磨出来的高效文生图方案。它不靠堆显存换效果,而是用蒸馏技术把大模型的精华“浓缩”出来——8步出图、照片级质感、中英文文字渲染稳得一批,16GB显存的消费级显卡就能扛住。更重要的是,它被完整集成进了一个开箱即用的ZEEKLOG镜像里,连Gradio界面都给你调好了配色和字体,连“怎么输入中文”这种细节都考虑到了。 这篇文章不讲原理推导,不列参数表格,也不让你手动clone仓库、pip install一堆包。我们就用最直白的方式,带你从零开始,在5分钟内看到第一张由Z-Image-Turbo生成的高清图像。你不需要懂Diffusers,不需要会调acceler

By Ne0inhk
Gemini 无损去水印神器:基于数学算法的纯前端解决方案

Gemini 无损去水印神器:基于数学算法的纯前端解决方案

🎯 Gemini 无损去水印神器:基于数学算法的纯前端解决方案 🔗 项目地址:gemini-watermark-remover 🌐 在线体验:banana.ovo.re ⭐ 如果觉得有用,请给项目点个 Star! 📖 引言 随着 Google Gemini AI 图像生成功能的普及,越来越多的用户开始使用它来创作各种精美的图片。然而,Gemini 生成的图片右下角都会带有一个半透明的水印 Logo,这在某些场景下可能会影响图片的使用效果。 今天给大家推荐一个开源项目 gemini-watermark-remover,它能够完美无损地移除 Gemini 图片上的可见水印,而且完全在浏览器端运行,无需上传图片到服务器,充分保护用户隐私! ✨ 核心特性 🔒 100% 客户端处理,隐私至上 * 无需后端服务器:所有图片处理都在浏览器本地完成 * 零数据上传:图片永远不会离开你的设备 * 即开即用:打开网页即可使用,无需注册登录 🎯 数学精确,非 AI 模型 * 基于反向 Alpha 混合算法(

By Ne0inhk

安卓系统Chrome内核:Android System WebView

com.google.android.webview 安卓8.0可以使用Android System WebView v138 安卓7.0可以使用Android System WebView v119 安卓6.0可以使用Android System WebView v106 安卓5.0可以使用Android System WebView v95 网盘下载1:https://down666.lanzoul.com/b01hjlghc 提取码:7x8i ------旧版网盘下载1:https://down666.lanzoul.com/b01hjlgje 提取码:aw3t 网盘下载2:https://www.mediafire.com/folder/cimpgytm5w2t8 有的安卓浏览器比如“X浏览器”自身是不带Chrome内核的,

By Ne0inhk
基于java Web 健身房注册管理系统设计与实现

基于java Web 健身房注册管理系统设计与实现

博主介绍:翰文编程 专注于Java(springboot ssm 等开发框架) vue  .net  php phython node.js    uniapp 微信小程序 等诸多技术领域和课设项目实战、企业信息化系统建设,从业十八余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了2000+题目解决方法案例  方便大家学习使用 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人 文末下方有源码获取地址 4系统概要设计 4.1系统功能模块设计 系统主要功能各功能结构图模块如图4-1所示:                                     图4-1 功能结构图 4.2数据库设计 4.2.1数据库设计原则 4.2.2数据库表的设计 根据需求分析,本健身房平台的数据库表,具体设计如下: 1 会员( 会员编号,用户名,密码,姓名,

By Ne0inhk