springboot项目的优雅关闭方式

本案例使用的是springboot2.0.4

当把打包好的jar包发布到服务器,并通过java -jar运行,一般要把springboot项目关闭大多数都是先找到项目的pid,然后直接kill pid,不过这种方法在特殊需求场景下不太合适(不安全),同时也不优雅。下面通过actuator来让springboot项目关闭优雅化。
先导入maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

然后切换到application.properties文件,添加

# 启用shutdown
management.endpoint.shutdown.enabled=true
# 公开所有的端点
management.endpoints.web.exposure.include=*

目前只要做到这样就可以实现springboot项目的优雅关闭了
只要模拟一个POST请求,请求url默认为
http://host:port/actuator/shutdown
返回

{"message":"Shutting down, bye..."}

说明优雅关闭成功

——————————————–手动分割线————————————————-

如果只是这样的话,还是存在很大的安全问题,当外人知道你的项目ip地址和端口号,谁都可以模拟该请求关闭你的服务器,这是必须避免的问题。
同样切换到application.properties文件,添加如下

#启用shutdown
management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=*
# 自定义管理端点的前缀(保证安全)
management.endpoints.web.base-path=/MyActuator
# 自定义端口
management.server.port=12581
# 不允许远程管理连接(不允许外部调用保证安全)
management.server.address=127.0.0.1

自定义management.endpoints.web.base-path这样别人就不知道你的关闭服务器的请求路径是什么了。换句话说关闭服务器的链接就变成了这个
http://host:port/MyActuator/shutdown

光自定义management.endpoints.web.base-path安全性还不够,我们还要避免在服务器外面关闭服务器,这样就算别人知道你的ip地址、端口号和请求路径也无法干扰服务器了。
设置management.server.address为本地ip这样就不能远程访问了。同时还需注意一点就是management.server.port这个对应的端口号,不能和你的tomcat服务器端口号一样。否则会导致management.server.address失效,随意一个空闲端口号即可。
这样关闭服务器的时候,首先要登录服务器,本地以POST方式请求该链接,
如果是linux系统,直接curl -X POST http://127.0.0.1:12581/MyActuator/shutdown即可关闭。
注意一点,这里的port就是你在application.properties配置的management.server.port。
好了目前就已经可以做到安全且优雅的关闭springboot项目了。

——————————————手动分割线————————————————-

虽然已经能安全且优雅的关闭springboot项目了,但是假如只是想重启下项目,想想还要输入这么多且长的指令curl、java -jar等。那有没有比较方便的方式呢,当然就是靠万能的shell脚本来解决了。(停止项目也是如此,新创建一个shell里面就一行代码curl -X POST http://127.0.0.1:12581/MyActuator/shutdown即可)
创建一个shell脚本,编写一下内容。(写的一般般,借鉴下即可)

#!/bin/bash
PORT=$(netstat -ntulp | grep 12580)
# 如果PORT不为空说明有程序占用该端口号
if [[ -n $PORT ]]; then
        echo "The server is open, ready to close"
        RESULT="000"
        while [[ $RESULT == "000" ]]; do
                echo "Closing down ..."
                # 优雅关闭springboot项目
                RESULT=$(curl -X POST 127.0.0.1:12581/MyActuator/shutdown)
                sleep 2
        done
        echo "Close off success"
fi
echo "Being started ..."
# 开启项目
/usr/local/work/finalab/jdk-10.0.2/bin/java -jar /usr/local/work/finalab/finalab.jar > log.info 2>log.error &

大致说下运行的思路,假如该端口号已经被占用,说明该springboot项目正在运行,就把它关闭,关闭完成后在打开springboot项目,如果该端口号不被占用则直接开启项目。
接下来说下编写的细节

netstat -ntulp | grep 12580 

执行该命令,如果12580端口号空闲,则会返回空。不为空就返回该端口号信息。

if [[ -n $PORT ]];

shell 中利用 -n 来判定字符串非空。

while [[ $RESULT == "000" ]]; do
        echo "Closing down ..."
        # 优雅关闭springboot项目
        RESULT=$(curl -X PORT 127.0.0.1:12581/MyActuator/shutdown)
        sleep 2
done

中间关闭springboot项目为什么用while呢同时也用到了sleep,这么做主要是尽可能避免重复请求,和请求失败后能够继续尝试请求。

/usr/local/work/finalab/jdk-10.0.2/bin/java -jar /usr/local/work/finalab/finalab.jar > log.info 2>log.error &

这里在finalab.jar文件后面 > log.info 2>log.error &
第一个>就是把项目运行控制台的内容输入到同级目录下的log.info(没有这个文件的话,会自动创建),2代表错误信息,就是把错误信息输出到log.error文件中,最后的&代表项目在后台运行,这样关闭控制台,项目就不会挂掉了。
如果从本地把jar上传到服务器,该服务器已经有该jar老版本项目正在运行中,替换后是不用重启项目的。

猜你喜欢

转载自blog.csdn.net/XlxfyzsFdblj/article/details/82054744