Spring boot 2.1版本、2.3及以上版本使用actuator实现优雅关闭程序
优雅停机
主要应用在版本更新的时候,为了等待正在工作的线程全部执行完毕,然后再停止
2.3及以上版本
1.maven引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.修改配置文件
management:endpoint:shutdown:enabled: trueendpoints:web:exposure:include: "shutdown"base-path: /monitor
2.1版本
除以上两步外尚需修改Application启动类
tomcat容器
package com.example;import org.apache.catalina.connector.Connector;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextClosedEvent;import com.example.framework.datasource.DynamicDataSourceContextHolder;import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** 启动程序*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@MapperScan("com.example.*.mapper")
//@EnableScheduling
public class NumberoneApplication
{public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);public static void main(String[] args){// System.setProperty("spring.devtools.restart.enabled", "false");SpringApplication.run(NumberoneApplication.class, args);log.info("----- Start Successful~启动成功 -----");}/*** 用于接受 shutdown 事件*/@Beanpublic GracefulShutdown gracefulShutdown() {return new GracefulShutdown();}/*** 配置tomcat** @return*/@Beanpublic ServletWebServerFactory servletContainer() {TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();tomcat.addConnectorCustomizers(gracefulShutdown());return tomcat;}/*** 优雅关闭 Spring Boot。容器必须是 tomcat*/private class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {private final Logger log = LoggerFactory.getLogger(GracefulShutdown.class);private volatile Connector connector;private final int waitTime = 10;@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 进程在" + waitTime + " 秒内无法结束,尝试强制结束");}} 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}}}
}
测试验证
测试
通过postman或curl -X POST http://localhost:8080/*/shutdown
发送请求验证
control内添加方法
@RequestMapping(value = "/a/testClose",method= RequestMethod.GET)@ResponseBodypublic String sayHi() throws InterruptedException {// 模拟复杂业务耗时处理流程Thread.sleep(10 * 1000L);return "success";}
启动项目,使用postman测试 ,会等待10s后显示请求成功,等待中…:
验证
2.1.1版本 Tomcat容器验证成功(无论是通过通过post方式调用接口或是程序命令窗口ctrl+c退出均优雅关闭程序)
参考网址
Spring boot 2.0 之优雅停机()
Spring Boot 内嵌容器 Tomcat / Undertow / Jetty 优雅停机实现
Spring Boot 2.0 实现优雅停机
再谈spring boot 优雅停机
使用actuator优雅地停止SpringBoot应用
curl 命令模拟 HTTP GET/POST 请求
Windows使用curl发送GET、POST请求
若依文档-集成actuator实现优雅关闭应用
spring文档
Spring boot 2.1版本、2.3及以上版本使用actuator实现优雅关闭程序相关推荐
- Spring Boot 3.0.0 发布第一个里程碑版本M1,你的 Java 升到 17 了吗?
欢迎关注方志朋的博客,回复"666"获面试宝典 文章来源:程序猿DD 2022年1月20日,Spring官方发布了Spring Boot 3.0.0的第一个里程碑版本M ...
- Spring Boot 2.4.3、2.3.9 版本发布,你准备好了吗?
新年上班第一天,Spring Boot 就发布了最新的2.4.3 .2.3.9 版本.心急的小伙伴现在可从 repo.spring.io 和 Maven Central 获得相关内容. <par ...
- spring boot / cloud (二十) 相同服务,发布不同版本,支撑并行的业务需求
有半年多没有更新了,按照常规剧本,应该会说项目很忙,工作很忙,没空更新,吧啦吧啦,相关的话吧, 但是细想想,是真的么?,忙到这几个字都没时间打么?毕竟大家都很忙的,所以忙并不是啥理由. 那是因为啥呢? ...
- Spring Boot + OAuth2.0 实现微信扫码登录,这才叫优雅
点击"终码一生",关注,置顶公众号 每日技术干货,第一时间送达! 微信开放平台:微信扫码登录功能 官方文档:https://developers.weixin.qq.com/doc ...
- Spring Boot + OAuth2.0 实现微信扫码登录,这才叫优雅!!
微信开放平台:微信扫码登录功能 官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_ ...
- Spring Boot + MDC 实现全链路调用日志跟踪,这才叫优雅!
欢迎关注方志朋的博客,回复"666"获面试宝典 1.简介: MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j .logback及log4j ...
- 前瞻:Spring Boot 2.4.0 第二个里程碑版本发布
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | https://www.oschina.net ...
- Spring Boot 1.0和Spring Boot 1.0.1错误修复版本
Spring Boot团队最近宣布了Spring Boot 1.0版本 ,随后是Spring Boot 1.0.1.RELEASE ,这是一个错误修复版本,其中还包含一些新功能. Spring Boo ...
- Spring 应用开发框架 Spring Boot 2.3.0 最新版本发布
Spring Boot 项目旨在简化创建产品级的 Spring 应用和服务.你可通过它来选择不同的 Spring 平台.可创建独立的 Java 应用和 Web 应用,同时提供了命令行工具来允许 'sp ...
- spring boot和spring cloud版本冲突解决方案
spring cloud和springboot版本是需要匹配才能一起使用的.在新建项目的时候,如果两者版本不一致,很有可能会导致项目启动失败. spring cloud和springboot的版本对应 ...
最新文章
- AI机器学习科研助力 | 计算机科学方向一对一科研项目
- php中转,使用 PHP Curl 做数据中转
- vmware-tools安装指南
- Ansible-Playbook-template算数运算以及流程控制
- idea中如何创建servlet文件
- 大数据 互联网架构阶段 Redis
- Problem G. Pandaria(线段树合并 + Kruskal 重构树)
- 【转】第01课:生活中的监听模式——一坑爹的热水器
- C语言实现单链表面试题汇总
- 成员函数指针与高性能的C++委托(上篇)
- 反射(3)—动态、静态代理
- lambda python aws_AWS Lambda Layer For Python Pakage
- 1470. 重新排列数组
- CMap的使用(转)
- 图像增强--视网膜皮层Retinex算法(二)
- php opendir 相对路径,我是wamp环境,怎么样让php的opendir函数可以接受相对路径?...
- PKPM结构设计软件案例教学
- 10个容易被接受的辞职理由
- 量化研究 | 策略在指数与主连复权的差异化分析(二)
- 批量提取 srt 字幕文件中的文字
热门文章
- php 获取客户端的ip、地理信息、浏览器信息、本地真实ip
- GridView的DataKeyNames属性(转)
- 国内外著名CAD、CAM雕刻软件介绍
- [20171120]11G关闭直接路径读.txt
- 随心所欲玩复制 详解robocopy (完)
- Linux如何产看系统信息
- -Dmaven.multiModuleProjectDirectory system propery is not set.
- java for语句
- Windows 7 通过无线网卡,模拟Wifi,实现手机,电脑等无线设备共享上网
- 隐马尔可夫模型(HMM)简介