优雅关闭项目
之前对java中的延迟任务进行了了解,但是对于实现延迟队列的一些方式(延迟队列,环形队列等),如果使用这些方式,在生产上,如果需要重启项目的话,那缓存中的数据如何进行保存,因此在网上搜罗了一些关于java优雅关闭的一些博客,即在ShutDownHook钩子函数中加入一些将延迟队列中的数据存储起来的方法
Linux的信号机制
kill命令可将指定的信号发送给相应的进程,linux中常见的信号如下:
1 SIGHUP 挂起进程
2 SIGINT 终止进程
3 SIGGQUIT 停止进程
9 SIGKILL 无条件终止进程
15 SIGTERM 尽可能终止进程
17 SIGSTOP 无条件停止进程,但不是终止
18 SIGTSTP 停止或者暂停进程,但不终止进程
19 SIGCONT 继续运行停止的进程
默认情况下kill命令使用的是
kill -15
,此时,如果java程序中定义的shutDownHook时,会触发; 如果使用kill -9
则不会触发钩子
- 1、ShutDownHook函数
/**
* cmd执行javac 编译后 使用java执行class文件
* 执行了 java TestShutDownHook 之后,输出“main executing”
* 但按 Ctrl+c之后,会输出shutDownHook execute
* 此时代表钩子函数执行了
*/
public class TestShutDownHook {
public static void main(String[] args) {
System.out.println("main executing");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("shutDownHook execute");
}));
try {
TimeUnit.DAYS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
以上代码在linux系统中执行 kill -15 test.jar 时,会回调ShutDownHook方法
- 2、springboot中的ShutDownHook
springboot项目中可以在自定义Bean对象,在启动时,添加ShutDownHook
package com.xsxy.alltestproject.springbootShutDownHook;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class SpringbootShutDownHook {
@PostConstruct
public void registerShutDownHook(){
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("springboot execute shutdownhook");
}));
}
}
测试:
打出jar包后,使用java -jar test.jar 启动springboot项目
nohup java -jar all-test-project-0.0.1-SNAPSHOT.jar &
-->
[1] 6641
使用kill -15 终止进程,会将springboot execute shutdownhook
日志输出到nohup文件中
而使用kill -9时,并不会调用ShutDownHook的方法
以下为网上的案例未经过测试:
- 3、 实现SignalHandler
public class KillHandler implements SignalHandler {
public void registerSignal(String signalName) {
Signal signal = new Signal(signalName);
Signal.handle(signal, this);
}
@Override
public void handle(Signal signal) {
if (signal.getName().equals("TERM")) {
//
} else if (signal.getName().equals("INT") || signal.getName().equals("HUP")) {
//
} else {
//
}
}
}
程序启动时实例化一个KillHandler,注册TERM信号。
KillHandler killHandler = new KillHandler();
killHandler.registerSignal(“TERM”);
这样,在进程被kill的时候就会触发KillHandler的handle方法。
相关博客 https://blog.csdn.net/u011001084/article/details/73480432 https://blog.csdn.net/m0_37793798/article/details/84206167 https://blog.csdn.net/chinrui/article/details/78685032