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

【C语言】排序算法——快速排序详解(含多种变式)!!!

【C语言】排序算法——快速排序详解(含多种变式)!!!

【C语言】排序算法——快速排序详解(含多种变式)!!! * 前言 * 一 、快速排序(初阶) * 1. 视频演示 * 2. 算法思想 * 3. 实现思路 * (1)定key值 * (2)大小交换 * (3)循环 * (4)交换key * (5)分割区间 * (6)结束 * 4. 实现代码 * 二 、快速排序(中阶) * 1. 存在的问题 * 2. 优化(三数取中) * 3. 实现代码(中阶) * 三 、快速排序(高阶) * 1. 仍存在的问题 * 2. 优化(小区间优化) * 3. 实现代码(高阶)

By Ne0inhk
Python安装最新(2026版)python最新版安装(图文并茂-详细)

Python安装最新(2026版)python最新版安装(图文并茂-详细)

目录 * 第一步:Python安装 * 1、登录官网 * 2、下载Windows版本 * 3、我喜欢下载最新版的前一版 * 4、开始安装 * 5、照着我安装 * 6、安装成功 * 7、校验成功 * 第二步:Pycharm安装 * 1、登录官网 * 2、点击下载 * 3、点击下载Windows版本 * 4、安装Pycharm * 第三步:启动Pychamr+导入Python(至关重要) * 1、创建项目成功 * 2、安装中文插件(如果已经是中文忽略此步骤) * 3、导出刚刚安装的Python(非常重要) * 4、导入成功,运行 专栏导读 ❤️ 欢迎各位佬关注! ❤️ 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📕 此外还有python基础专栏:请点击——>

By Ne0inhk
[Python] 进阶之路:模块、包和异常处理

[Python] 进阶之路:模块、包和异常处理

在掌握了Python的类与对象后,下一步是深入理解模块化开发和异常处理。模块与包帮助我们组织代码,增强代码的可维护性和重用性,而异常处理则是编写健壮代码的重要技能。本文将系统讲解Python中模块、包和异常处理的核心概念与实用技巧。 一、模块:代码组织的基本单位 1.1 什么是模块? 模块(Module)是Python中用于组织代码的基本单位,一个.py文件就是一个模块。通过模块,我们可以将相关功能的代码放在一起,便于重用和维护。 例如,一个名为math_utils.py的模块可能包含一些数学相关的函数: # math_utils.pydefadd(a, b):return a + b defsubtract(a, b):return a - b 1.2 如何导入模块? Python使用import关键字导入模块。以下是常见的导入方式: # 导入整个模块import math_utils print(math_

By Ne0inhk

关于 ComfyUI 的 Windows 本地部署系统环境教程(详细讲解Windows 10/11、NVIDIA GPU、Python、PyTorch环境等)

在本地部署 ComfyUI 时,确保 Python、PyTorch、CUDA 等组件的版本能完美匹配,这对避免安装报错和保证稳定运行至关重要。 以下内容是整合了一份核心组件的版本适配对照表,并配上不同显卡的配置建议,希望能帮助你顺利部署。 一、准备阶段 1. 系统与硬件确认 * 确保你的系统为 Windows 10 或更高版本。 * 拥有一块 NVIDIA 显卡(最好支持较新 CUDA 架构)。 * 显存建议至少 6-8 GB,如果你要做高清、大分辨率或多插件 (ControlNet/LoRA) 的生成,建议 12 GB 以上。 * NVIDIA 驱动建议更新为与所选 CUDA 版本兼容的最新驱动。 * 你可运行 nvidia-smi 在终端查看当前驱动版本及支持的 CUDA 最高版本。 * 硬盘建议为 SSD,并有充足可用空间(

By Ne0inhk