我们看一下我们kill命令

zanglikun@zanglikundeMacBook-Pro ~ % kill -l
HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URG STOP TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH INFO USR1 USR2

好家伙,这么多信号!序号从1是从左往右依次递增的。9号是KILL、15号是TREM

Ctrl + C 是给程序发送INT信号 等价于 kill -2。

kill -2 PID真实含义是:是发送SIGINT信号,它是一个可以被捕获的信号,程序可以捕获这个信号,并执行一些清理工作,然后终止进程。

kill -9 PID真实含义是:发送SIGKILL信号,它是一个不可以被捕获的信号,程序无法捕获这个信号,它会立即终止进程。

kill -15 PID真实含义是:给程序发送发送SIGTERM信号,它是一个可以被捕获的信号,程序可以捕获这个信号,并执行一些清理工作,然后终止进程。

我们停止服务的时候,往往就在内置脚本执行了kill -9 PID的命令。

但是如果我们进程中,有些业务没执行完毕,比如:用户导出Excel。线程执行一半。进程没了。用户就会丢失这个请求了!

获取PID:jps -l

经过测试:SpringBoot项目(2.1.0)如果主线程方法添加ShutdownHook后。执行kill -9 PID不会出发Hook执行。kill -15 PID会触发Hook执行。(IDEA点击终止按钮也会触发Hook)

测试优雅下线执行流程

public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        // 添加服务优雅下线入口机制
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Shut Down 执行了!开始执行各个Bean的销毁方法");
            }
        }));
    }
}

编写一个类TestBeanDestory,实现DisposableBean接口。以便于测试Bean销毁时机

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class TestBeanDestory implements InitializingBean,DisposableBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("IOC容器加载我了。ClassName是TestBeanDestory");
    }
    @Override
    public void destroy() throws Exception {
        // 想要获取Bean被销毁时触发内容,请在Bean实现DisposableBean接口重写destroy()方法
        System.out.println("TestBeanDestory被销毁了");
    }
}

看下日志输出吧

IOC容器加载我的时候,触发了。ClassName是TestBeanDestory
Shut Down 执行了!开始执行各个Bean的销毁方法
TestBeanDestory被销毁了

结论:Hook执行后,会调用Bean的destoty()方法。

分布式环境优雅下线

如果是分布式环境:往往都是在注册中心注册了多个相同的服务。比如商品服务A,商品服务B。我们要停止商品服务A。那就先将注册中心,将A剔除。然后等待几秒。在执行kill -15 进行处理

如果是单机下线

我觉得大部分业务都是用nginx反向代理的。

建议将nginx把反向代理删除。以免后续请求进入。kill -15后。在启动服务。再启动Nginx的反向代理。

特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取全部资料 ❤