Spring Boot 在关闭时,如果有请求没有响应完,在不同的容器会出现不同的结果,例如,在 Tomcat 和 Undertow 中会出现中断异常,那么就有可能对业务造成影响。所以,优雅停机非常有必要性,目前官方是没有提供很好的策略来实现。

Each SpringApplication registers a shutdown hook with the JVM to ensure that the ApplicationContext closes gracefully on exit. All the standard Spring lifecycle callbacks (such as the DisposableBean interface or the @PreDestroy annotation) can be used.

Spring Boot Application 在接收到停机信号后,可以通过 DisposableBean 接口 、 @PreDestroy 注解 或者 ContextClosedEvent 事件来处理优雅停机的相关逻辑。

版本信息

Spring Boot 版本: 2.0.0.RELEASE

Tomcat 优雅停机

@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}/*** 用于接受 shutdown 事件*/@Beanpublic GracefulShutdown gracefulShutdown() {return new GracefulShutdown();}@Beanpublic ServletWebServerFactory servletContainer() {TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();tomcat.addConnectorCustomizers(gracefulShutdown());return tomcat;}/*** 优雅关闭 Spring Boot*/private class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {private final Logger log = LoggerFactory.getLogger(GracefulShutdown.class);private volatile Connector connector;private final int waitTime = 30;@Overridepublic void customize(Connector connector) {this.connector = connector;}@Overridepublic void onApplicationEvent(ContextClosedEvent contextClosedEvent) {this.connector.pause();Executor executor = this.connector.getProtocolHandler().getExecutor();if (executor instanceof ThreadPoolExecutor) {try {ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;threadPoolExecutor.shutdown();if (!threadPoolExecutor.awaitTermination(waitTime, TimeUnit.SECONDS)) {log.warn("Tomcat thread pool did not shut down gracefully within " + waitTime + " seconds. Proceeding with forceful shutdown");}} catch (InterruptedException ex) {Thread.currentThread().interrupt();}}}}}

Undertow 优雅停机

@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}/*** 优雅关闭 Spring Boot*/@Componentpublic class GracefulShutdown implements ApplicationListener<ContextClosedEvent> {@Autowiredprivate GracefulShutdownWrapper gracefulShutdownWrapper;@Autowiredprivate ServletWebServerApplicationContext context;@Overridepublic void onApplicationEvent(ContextClosedEvent contextClosedEvent){gracefulShutdownWrapper.getGracefulShutdownHandler().shutdown();try {UndertowServletWebServer webServer = (UndertowServletWebServer)context.getWebServer();Field field = webServer.getClass().getDeclaredField("undertow");field.setAccessible(true);Undertow undertow = (Undertow) field.get(webServer);List<Undertow.ListenerInfo> listenerInfo = undertow.getListenerInfo();Undertow.ListenerInfo listener = listenerInfo.get(0);ConnectorStatistics connectorStatistics = listener.getConnectorStatistics();while (connectorStatistics.getActiveConnections() > 0){}}catch (Exception e){// Application Shutdown}}}
}
@Component
public class GracefulShutdownWrapper implements HandlerWrapper{private GracefulShutdownHandler gracefulShutdownHandler;@Overridepublic HttpHandler wrap(HttpHandler handler) {if(gracefulShutdownHandler == null) {this.gracefulShutdownHandler = new GracefulShutdownHandler(handler);}return gracefulShutdownHandler;}public GracefulShutdownHandler getGracefulShutdownHandler() {return gracefulShutdownHandler;}}
@Component
@AllArgsConstructor
public class UndertowExtraConfiguration {private final GracefulShutdownWrapper gracefulShutdownWrapper;@Beanpublic UndertowServletWebServerFactory servletWebServerFactory() {UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();factory.addDeploymentInfoCustomizers(deploymentInfo -> deploymentInfo.addOuterHandlerChainWrapper(gracefulShutdownWrapper));factory.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ENABLE_STATISTICS, true));return factory;}}

Jetty 优雅停机

默认支持所有请求完毕后再关闭,缺点:客户端接收不到响应,有待改进!

Spring Boot 内嵌容器 Tomcat / Undertow / Jetty 优雅停机实现相关推荐

  1. Spring Boot 容器选择 Undertow 而不是 Tomcat Spring Boot 内嵌容器Unde

    Spring Boot 内嵌容器Undertow参数设置 配置项: # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动 ...

  2. Netweaver的端口号和Spring boot内嵌的Tomcat端口

    Netweaver FM : TH_GET_VIRT_HOST_DATA Spring Boot Spring Boot will launch an embedded Tomcat instance ...

  3. Spring Boot 内嵌容器Undertow参数设置

    配置项: # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动项目会报错:打开文件数过多server.undertow. ...

  4. spring boot内嵌tomcat优雅的开启apr模式

    文章目录 简介 Win下开启APR Linux下开启APR 把lib打进jar包 简介 环境: jdk8.spring boot 2.3.4.RELEASE.centOS7.3.win7 在sprin ...

  5. spring boot实战(第七篇)内嵌容器tomcat配置

    spring boot默认web程序启用tomcat内嵌容器tomcat,监听8080端口,servletPath默认为 / 通过需要用到的就是端口.上下文路径的修改,在spring boot中其修改 ...

  6. Spring Boot 内嵌Tomcat的端口号的修改

    操作非常的简单,不过如果从来没有操作过,也是需要查找一下资料的,所以,在此我简单的记录一下自己的操作步骤以备后用! 1:我的Eclipse版本,不同的开发工具可能有所差异,不过大同小异 2:如何进入对 ...

  7. Spring Boot内嵌tomcat关于getServletContext().getRealPath获取得到临时路径的问题

    问题记录 问题场景:修改头像业务,文件上传 代码 // 上传的文件.../upload/文件.png//在javaWeb中我们会用HttpServletRequest来获取上下文路径,当然sessio ...

  8. 修改Spring boot内置的tomcat端口

    介绍两种种简单的修改spring boot内置端口的方法: 第一种:在入口直接设置端口,代码如下所示: public static void main(String[] args){SpringApp ...

  9. 总在说 Spring Boot 内置了 Tomcat 启动,那它的原理你说的清楚吗?

    前言 不得不说SpringBoot的开发者是在为大众程序猿谋福利,把大家都惯成了懒汉,xml不配置了,连tomcat也懒的配置了,典型的一键启动系统,那么tomcat在springboot是怎么启动的 ...

最新文章

  1. shell awk实战
  2. 21世纪科技生态面临第三次全球标准
  3. pytorch_lightning Default process group is not initialized
  4. oracle定时任务的编写及查看删除
  5. 多用户企业文件管理系统源码_固定资产管理系统的细节分析
  6. 表面粗糙度的基本评定参数是_表面粗糙度100问,讲得明明白白
  7. oracle数据库sql的执行过程,Oracle体系结构之SQL语句的执行过程
  8. JAVA类与对象(一)----基础概念理解
  9. pytorch torch.optim.Optimizer
  10. sql 在某表中加入一列count所有数据_执行COUNT(1)、COUNT(*) 与 COUNT(列名) 到底有什么区别?...
  11. Three.js 关于立方体贴图产生边缘锯齿问题
  12. R语言编程艺术(4)R对数据、文件、字符串以及图形的处理
  13. 光盘放进电脑读不出来_U盘插入电脑读不出来?学会这3招,轻松解决USB无法读取的问题...
  14. 错误提示之:SQL—无法在服务器上访问指定的路径或文件。请确保您具有必需的安全权限且该路径或文件存在。...
  15. java - 操作系统 Linux
  16. 时间序列分析与非参数统计
  17. STM32cubeMX--增量式PID调节电机速度(霍尔编码器)
  18. mysql中查询编辑器_万能数据库查看器|Universal SQL Editor(万能SQL编辑器)下载 v1.8 官方版 - 比克尔下载...
  19. ubuntu系统重装恢复步骤
  20. 华为2022硬件工程师招聘全程经验

热门文章

  1. JS Bin Tips and Bits • About
  2. 史上最通俗的《深入理解计算机网络》目录
  3. Web前端技术趋势:HTML5仍不宜用作生产
  4. 什么是OAuth 2.0
  5. 基本操作:Go创建GraphQL API
  6. laravel5.4 刷新过快,出现The only supported ciphers are AES-128-CBC and AES-256-CBC
  7. Whoops, looks like something went wrong.
  8. PDO::ATTR_EMULATE_PREPARES
  9. 理解Linux的overcommit memory
  10. Go 语言之父详述切片与其他编程语言数组的不同