本案例使用的是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