SpringBoot程序正确停⽌的姿势
Spring Boot提供了2种优雅关闭进程的⽅式:
1. 基于管理端⼝关闭进程
2. 基于系统服务⽅式关闭进程
基于管理端⼝关闭进程
基于管理端⼝⽅式实现进程关闭实际上是模块spring-boot-actuator提供的功能。
⾸先,需要在项⽬中添加对应模块依赖配置。
添加Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
添加Gradle依赖
dependencies {
compile("org.springframework.boot:spring-boot-starter-actuator")
}
其次,在配置⽂件中添加对应的参数配置(以⽂件application.properties为例说明)。
# 允许执⾏关闭操作
# 处于安全考虑,只允许在本地指定关闭操作
management.server.address=127.0.0.1
# 管理端⼝
management.server.port=8000
# 管理URL基础路径,默认为“/”
# 配置关闭进程Endpoint
# 对外暴露管理Endpoint
实践中通常将上述关闭进程的URL调⽤写到脚本中,同时还可以结合别的⽅式⼀起确保进程⼀定能退出,如下为脚本⽰例(pname指进程名称):#!/bin/bash
# 先通过管理端⼝关闭进程
curl -X POST 127.0.0.1:8000/ops/shutdown --connect-timeout 3 --max-time 5
# 再次通过名称检查进程是否被成功停⽌
count=`ps -ef |grep pname |grep -v "grep" |wc -l`
if [ $count -gt 0 ]; then
if [ -f "$pid_file" ]; then
# 如果存在进程ID⽂件,则读取进程ID使⽤信号量通知⽅式关闭进程
pid=`cat $pid_file`
kill -15 $pid
else
# 通过名称⽅式查到进程ID,使⽤信号量通知⽅式关闭进程
pid=`ps -ef |grep pname |grep -v "grep"| awk '{print $2}'`
kill -15 $pid
fi
fi
通过系统服务⽅式停⽌进程
Spring Boot⽀持直接将打包好的可执⾏jar包以系统服务⽅式运⾏,具体实现⽅式如下所述。
⾸先,将应⽤打包为完全可执⾏的jar包。
Maven打包配配置
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 这个配置⾮常重要,使打包好的jar包具备可执⾏权限-->
<executable>true</executable>
</configuration>
</plugin>
Gradle打包配置
bootJar {
launchScript()
}
其次,将打包好的应⽤jar包添加为系统服务(在ubuntu18.04 LTS上实现,基于systemd)
1.假设将Spring Boot应⽤安装到/var/myapp⽬录下:将上述打包好的jar包拷贝到/var/myapp(⽬录不存在,⼿动创建)
2.在/etc/systemd/system下添加指定名称的系统服务:myapp.service,内容如下:
[Unit]
Description=myapp
After=syslog.target
[Service]
User=root  ## 注意:这⾥配置的是将来启动该服务的Linux系统⽤户名,影响权限
ExecStart=/var/myapp/myapp.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
3.启动服务
$ sudo systemctl enable myapp.service
$ sudo systemctl start myapp.service
如果需要查看应⽤启动⽇志,请执⾏:$ journalctl -f。
写在最后
我在中有讲到如何实现在进程退出之前做⼀些收尾的⼯作,这在Spring Boot中同样适⽤,只需要监听对应的信号量并注册JVM关闭钩⼦即可。
@SpringBootApplication
public class SpringbootApplication {
private static final Logger logger = Logger(SpringbootApplication.class);
public static void main(String[] args) {
// 在Spring Boot应⽤中通过监听信号量和注册关闭钩⼦来实现在进程退出之前执⾏收尾⼯作
// 监听信号量
Signal sg = new Signal("TERM");
Signal.handle(sg, new SignalHandler() {
@Override
public void handle(Signal signal) {
logger.info("do signal handle: {}", Name());
}
});
// 注册关闭钩⼦
@Override
public void run() {
// 执⾏收尾⼯作
logger.info("do something on shutdown hook");
maven打包本地jar包
}
});
SpringApplication.run(SpringbootApplication.class, args);
logger.info("Start DONE.");
}
}
另外,需要注意的是:在普通的Java应⽤程序中,当出现RuntimeExeception或OOM时会触发关闭钩⼦的执⾏;但是在Spring Boot应⽤中,当出现RuntimeException或OOM时并不会触发关闭钩⼦的执⾏(Spring Boot使⽤了嵌⼊式Tomcat)。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。