背景
现有微服务项目的各个微服务使用的是kill -9方式停止服务。这种方式显得略有些粗鲁,因为这样的应用停止方式,在停止的那一霎那,应用中正在处理的业务逻辑会被中断,导致生产义务异常情形。
需求
在对应用进程发送停止指令之后,能保证正在执行的业务操作不受影响。应用接收到停止指令之后的步骤应该是,停止接收访问请求,等待已经接收到的请求处理完成,并能成功返回
常用kill命令说明
kill 命令常用的信号选项:
(1) kill -2 pid 向指定 pid 发送 SIGINT 中断信号, 等同于 ctrl+c.
(2) kill -9 pid, 向指定 pid 发送 SIGKILL 立即终止信号.
(3) kill -15 pid, 向指定 pid 发送 SIGTERM 终止信号.
(4) kill pid 等同于 kill 15 pid
SIGINT/SIGKILL/SIGTERM 信号的区别:
(1) SIGINT (ctrl+c) 信号 (信号编号为 2), 信号会被当前进程树接收到, 也就说, 不仅当前进程会收到该信号, 而且它的子进程也会收到.
(2) SIGKILL 信号 (信号编号为 9), 程序不能捕获该信号, 最粗暴最快速结束程序的方法.
(3) SIGTERM 信号 (信号编号为 15), 信号会被当前进程接收到, 但它的子进程不会收到, 如果当前进程被 kill 掉, 它的的子进程的父进程将变成 init 进程 (init 进程是那个 pid 为 1 的进程)
一般要结束某个进程, 我们应该优先使用 kill pid , 而不是 kill -9 pid. 如果对应程序提供优雅关闭机制的话, 在完全退出之前, 先可以做一些善后处理.
解决方案分析
1.java底层对优雅停机的底层支持
java语言底层有机制能捕获到系统的SIGINT/SIGTERM停止指令的,具体是通过Runtime.getRuntime().addShutdownHook() 向JVM中注册一个Shutdown hook线程,当JVM收到停止信号后,该线程将被激活运行,这时候我们就可以向其他线程发出中断指令,进而快速而优雅地关闭整个程序。
2.springboot web项目的停机支持
- 外置tomcat支持优雅推出,提供了以下命令:
catalina.sh stop n , 先等 n 秒后, 然后停止