spring boot2.0实现优雅停机的方法
时间:2019-04-14
本文章向大家介绍spring boot2.0实现优雅停机的方法,主要包括spring boot2.0实现优雅停机的方法使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
前期踩的坑 (spring boot 1.x)
1. 添加mavne依赖
<!-- springboot监控 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
2. 启用shutdown
在配置文件里添加下面的配置
#启用shutdown endpoint的HTTP访问 endpoints.shutdown.enabled=true #不需要验证 endpoints.shutdown.sensitive=false
启动的时候可以看到下面的日志,就说明成功了
3. 优雅停机
发送POST请求 http://localhost:8080/shutdown
如果响应码是404 可以尝试POST http://localhost:8080/actuator/shutdown
spring boot 2.0
如果你使用的spring boot版本是2.x的就会发现,这些POST请求都会出现404的结果。
下面是spring boot 2.0 优雅停机的实现方式。
1.修改Application启动类
tomcat容器
@SpringBootApplication public class ShutdownApplication { public static void main(String[] args) { SpringApplication.run(ShutdownApplication.class, args); } /** * 用于接受 shutdown 事件 */ @Bean public GracefulShutdown gracefulShutdown() { return new GracefulShutdown(); } /** * 配置tomcat * * @return */ @Bean public 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; @Override public void customize(Connector connector) { this.connector = connector; } @Override public 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 */ @Component public class GracefulShutdown implements ApplicationListener<ContextClosedEvent> { @Autowired private GracefulShutdownWrapper gracefulShutdownWrapper; @Autowired private ServletWebServerApplicationContext context; @Override public 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; @Override public 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; @Bean public UndertowServletWebServerFactory servletWebServerFactory() { UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory(); factory.addDeploymentInfoCustomizers(deploymentInfo -> deploymentInfo.addOuterHandlerChainWrapper(gracefulShutdownWrapper)); factory.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ENABLE_STATISTICS, true)); return factory; } } }
2. 使用 kill命令杀死进程
使用下面的命令杀死进程。该命令是向 某个进程发送终止信号。
kill -15 [PID]
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
- 游戏服务器之内存数据库redis客户端应用(上)
- 游戏服务器之内存数据库redis客户端应用(下)
- 使用Python和Tesseract来识别图形验证码
- 高并发服务器的设计--连接池的设计
- Pwnable.tw刷题之Silverbullet破解过程分享
- 鸡肋CSRF和Self-XSS组合的变废为宝
- 简易--go语言redis连接池
- Golang中channel使用的一些小技巧
- Go语言的管道Channel用法实例
- 【数据库】MySQL进阶二、索引简易教程
- 【数据库】MySQL进阶六、模糊查询用法
- 【选择题】Java基础测试九(16道)
- 用Ansible自动供应vmware虚拟机--构建数据中心一体化运维平台第二篇
- 【编程题】Java编程题五(10道)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- SAP Spartacus把指定产品添加到购物车的API
- MyBatis源码解析之基础模块—Plugin
- php框架slim架构上存在XXE漏洞(XXE的典型存在形式)
- 个人博客搭建
- 安全箱子的秘密
- Linux 机器 CPU 毛刺问题排查
- phpwind 利用哈希长度扩展攻击进行getshell
- dotnet 构建 SourceRoot items must include at least one top-level item when DeterministicSourcePaths is
- Magicodes.IE 2.4版本发布
- EC2磁盘扩容-DiskPressure
- 谈一谈php://filter的妙用
- 新型php漏洞挖掘之debug导致的安全漏洞(Edusoho)
- CVE-2016-3714 - ImageMagick 命令执行分析
- 知乎某处XSS+刷粉超详细漏洞技术分析
- 【STM32H7】第12章 RL-TCPnet V7.X之TCP客户端