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文件中,最後的&代表項目在後臺運行,這樣關閉控制檯,項目就不會掛掉了。 
&一般常和nohup一起使用 nohup xxx & 
nohup不掛斷的運行(換句話說就是退出或者註銷當前賬戶後程序還能運行),但不能保證後臺運行。控制檯關閉後就掛了。 
& 代表可以後臺運行(控制檯關閉後對它沒影響) 
有關更多的nohup和&之間的關係請看https://www.cnblogs.com/jinxiao-pu/p/9131057.html

——————————————手動分割線————————————————-

當你把新版本的,jar項目上傳到服務器把原來的.jar替換,會發現並沒有自動幫我們重啓項目,換句話說你還需要先shutdown項目,再來java -jar運行,是不是感覺有些麻煩。我們能不能像tomcat的webapps那樣子自動更新項目呢 
請看下一篇文章《運用inotify實現springboot項目自動更新部署》 
https://blog.csdn.net/XlxfyzsFdblj/article/details/82110034 
 

發佈了58 篇原創文章 · 獲贊 12 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章