springboot项目优雅停机

触发时机:利用JVM的shutdownhook进行自定义控制

由于springboot本身已经注册了(自动注册ShutdownHook),且通过发布ContextClosedEvent事件,因此监听ApplicationListener事件即可

@Component
public class GracefulShutdownHandler implements ApplicationListener<ContextClosedEvent> {
    public static final AtomicBoolean contextClosed = new AtomicBoolean(false);
    private ApplicationContext applicationContext;
    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        if (contextClosed.compareAndSet(false, true)) {
                this.applicationContext = event.getApplicationContext();
                //TODO 优雅停机
            }
    }
}

修改的内容

一、停止接收HTTP新的请求(摘除流量,停止新请求打到机器上)

1、nginx等方式摘除流量
2、运维侧docker的优雅停机123
3、Springboot本身的优雅停机(注意:Springboot2.3版本,同时需要配合Tomcat 9.0.33(含)以上版本)

# 开启优雅停机,默认值:immediate 为立即关闭
server.shutdown=graceful
# 设置缓冲期,最大等待时间,默认:30秒
spring.lifecycle.timeout-per-shutdown-phase=30s

原理
是在AbstractApplicationContext.this.doClose();内开始触发的。

  • spring.lifecycle.timeout-per-shutdown-phase=30s
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration#defaultLifecycleProcessor

org.springframework.context.support.AbstractApplicationContext#doClose
org.springframework.context.support.DefaultLifecycleProcessor#onClose
  • 触发时机(通过SmartLifecycle的stop触发)
1、所有的Lifecycle进行处理:Phased作为key,相同PhasedLifecycle集合作为value组成Maporg.springframework.context.support.DefaultLifecycleProcessor#stopBeans

2、根据key倒叙排列,依次执行对应的Lifecycle集合的stop。每个key的处理之间,最多wait时间(spring.lifecycle.timeout-per-shutdown-phase),待处理完成后,才会执行下一个key的业务处理

	2.1Phased2147483647WebServerGracefulShutdownLifecycle进行shutdown处理(停止新请求的处理,并等待现有请求完成),最多wait时间(spring.lifecycle.timeout-per-shutdown-phase)
org.springframework.boot.web.context.WebServerGracefulShutdownLifecycle#stop

	2.2Phased2147483646WebServerGracefulShutdownLifecycle则会强制关闭容器
org.springframework.boot.web.reactive.context.WebServerStartStopLifecycle#stop
  • 使用配置server.shutdown=graceful
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getTomcatWebServer中创建webServer时使用

二、xxl-job的优雅停机(停止接收任务)

Map<String, XxlJobExecutor> xxlJobExecutorMap = applicationContext.getBeansOfType(XxlJobExecutor.class);
Optional.ofNullable(xxlJobExecutorMap).ifPresent(map -> {
                map.values().forEach(xxlJobExecutor -> {
                    xxlJobExecutor.destroy();
                });

三、普通Scheduled定时任务的优雅停机(停止接收任务)

Map<String, ThreadPoolTaskScheduler> taskSchedulerMap = applicationContext.getBeansOfType(ThreadPoolTaskScheduler.class);
Optional.ofNullable(taskSchedulerMap).ifPresent(map -> {
                map.values().forEach(taskScheduler -> {
                    ScheduledThreadPoolExecutor poolExecutor = taskScheduler.getScheduledThreadPoolExecutor();
                    taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
                    poolExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
                    poolExecutor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
                    taskScheduler.shutdown();
                });

四、springboot与rocketMQ的优雅停机

<dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>${rocketmq-spring-boot-starter.version}</version>
</dependency>
@Component
@RocketMQMessageListener(topic = "", consumerGroup = "", messageModel = MessageModel.CLUSTERING)
public class ConsumerRocketMQListener implements RocketMQListener<NotifyMqMessage> {
  @Override
    public void onMessage(NotifyMqMessage notifyMqMessage) {
    
    }
}
Map<String, DefaultRocketMQListenerContainer> mqConsumerMap = applicationContext.getBeansOfType(DefaultRocketMQListenerContainer.class);
Optional.ofNullable(mqConsumerMap).ifPresent(map -> {
                        map.values().forEach(DefaultRocketMQListenerContainer::stop);
                    });

五、其他

通过标识控制不同的功能的暂停

public static final AtomicBoolean contextClosed = new AtomicBoolean(false);
各个业务通过contextClosed.get()判断是否进入停机流程

  1. SpringBoot系列: 如何优雅停止服务 ↩︎

  2. SpringBoot应用服务启动与安全终止 ↩︎

  3. Java 技术栈中间件优雅停机方案设计与实现全景图 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值