优雅的关闭vertx

00 前言

什么叫优雅停机?简单说就是,在对应用进程发送停止指令之后,能保证正在执行的业务操作不受影响。应用接收到停止指令之后的步骤应该是,停止接收访问请求,等待已经接收到的请求处理完成,并能成功返回,这时才真正停止应用。
这种完美的应用停止方式如何实现呢?就Java语言生态来说,底层的技术是支持的,所以我们才能实现在Java语言之上的各个web容器的优雅停机。
在普通的外置的tomcat中,有shutdown脚本提供优雅的停机机制,但是我们在使用Spring boot的过程中发现web容器都是内置(当然也可使用外置,但是不推荐),这种方式提供简单的应用启动方式,方便的管理机制,非常适用于微服务应用中,但是默认没有提供优雅停机的方式。这也是本文探索这个问题的根本原因。
应用是否是实现了优雅停机,如何才能验证呢?这需要一个处理时间较长的业务逻辑,模拟这样的逻辑应该很简单,使用线程sleep或者长时间循环。我的模拟业务逻辑代码如下:

@GetMapping(value = "/sleep/one", produces = "application/json")
public ResultEntity<Long> sleepOne(String systemNo){
    logger.info("模拟业务处理1分钟,请求参数:{}", systemNo);
    Long serverTime = System.currentTimeMillis();
//        try {
//            Thread.sleep(60*1000L);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
    while (System.currentTimeMillis() < serverTime + (60 * 1000)){
        logger.info("正在处理业务,当前时间:{},开始时间:{}", System.currentTimeMillis(), serverTime);
    }
    ResultEntity<Long> resultEntity = new ResultEntity<>(serverTime);
    logger.info("模拟业务处理1分钟,响应参数:{}", resultEntity);
    return resultEntity;
}

验证方式就是,在触发这个接口的业务处理之后,业务逻辑处理时间长达1分钟,需要在处理结束前,发起停止指令,验证是否能够正常返回。验证时所使用的kill指令:kill -2(Ctrl + C)、kill -15、kill -9。

01 Java 语言的优雅停机

从上面的介绍中我们发现,Java语言本身是支持优雅停机的,这里就先介绍一下普通的java应用是如何实现优雅停止的。
当我们使用kill PID的方式结束一个Java应用的时候,JVM会收到一个停止信号,然后执行shutdownHook的线程。一个实现示例如下:

public class ShutdownHook extends Thread {
    private Thread mainThread;
    private boolean shutDownSignalReceived;

    @Override
    public void run() {
        System.out.println("Shut down signal received.");
        this.shutDownSignalReceived=true;
        mainThread.interrupt();
        try {
            mainThread.join(); //当收到停止信号时,等待mainThread的执行完成
        } catch (InterruptedException e) {
        }
        System.out.println("Shut down complete.");
    }

    public ShutdownHook(Thread mainThread) {
        super();
        this.mainThread = mainThread;
        this.shutDownSignalReceived = false;
        Runtime.getRuntime().addShutdownHook(this);
    }

    public boolean shouldShutDown(){
        return shutDownSignalReceived;
    }

}

其中关键语句Runtime.getRuntime().addShutdownHook(this);,注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用:

程序正常退出
使用System.exit()
终端使用Ctrl+C触发的中断
系统关闭
使用Kill pid命令干掉进程

02 vertx的优雅停机
vertx本身的close方法已经实现了他的优雅停机,我们只需保证java进程在vertx close结束后关闭即可,所以代码如下:

 Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            log.info("start stop vertx");
            Vertx vertx= SpringContextUtils.getBean(Vertx.class);
            CountDownLatch countDownLatch=new CountDownLatch(1);
            vertx.close(res->{
                countDownLatch.countDown();
            });
            try {
                countDownLatch.await(30, TimeUnit.SECONDS);
                log.info("stop vertx success");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }));
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值