SpringBoot优雅停机
优雅停机需要两个条件:
- serlvet容器支持
- 开启JMX或者endPoint
目前统一采用endpoint的http形式执行优雅停机,其依赖于Spring的监控组件spring-boot-starter-actuator
针对使用tomcat容器的SpringBoot项目,优雅停机步骤如下:
1.引入监控组件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>xx.xx.xx</version>
</dependency>
2.开启优雅停机功能
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=10s
management.endpoints.web.exposure.include=shutdown #包含shutdown即可
management.endpoint.shutdown.enabled=true
server.shutdown=graceful,优雅停机,
server.shutdown=immediate,表示立即停机�3.执行停机操作
curl -X POST http://localhost:3333/actuator/shutdown
线程池优雅停机
常用线程池有一下两个:
- ThreadPoolTaskScheduler
- �ThreadPoolTaskExecutor
参数配置
ThreadPoolTaskScheduler定时任务线程池,ThreadPoolTaskExecutor异步线程池,
两者都提供了
//表明等待所有线程执行完
executor.setWaitForTasksToCompleteOnShutdown(true);
//等待xx秒后强制停止
executor.setAwaitTerminationSeconds(10);
�Bean销毁影响线程池执行
当springboot中存在线程池时,优雅停机后,可能线程池中的线程还在继续运行时,其依赖的逻辑处理bean已经消费,这个会导致线程处理异常发生,不能够保证数据完整性。
dubbo优雅停机
@Bean
DubboShutdownListener dubboShutdownListener() {
return new DubboShutdownListener();
}
public static class DubboShutdownListener implements ApplicationListener, PriorityOrdered {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationStartedEvent) {
Runtime.getRuntime().removeShutdownHook(DubboShutdownHook.getDubboShutdownHook());
log.info("dubbo default shutdown hook removed,will be managed by spring");
} else if (event instanceof ContextClosedEvent) {
log.info("start destroy dubbo on spring close event");
DubboShutdownHook.getDubboShutdownHook().destroyAll();
log.info("dubbo destroy finished");
}
}
@Override
public int getOrder() {
return 0;
}
}
容器关闭时,调用DubboShutdownHook.getDubboShutdownHook().destroyAll()方法,将当前服务注册在注册中心的服务撤销,保证当前节点不会被消费者调用。
MQ优雅停机
总结
优雅停机优先级,要遵循以下顺序:
RestFul>Dubbo>MQ>线程池