SpringBoot最大特點便是簡化配置,提升開發效率,實現簡單部署就是通過內嵌一個Web容器,如果Tomcat、Jettty等。
對於SpringBoot應用,只需打包成一個簡單的Jar包,然后執行java -jar就可以啟動,是一種非常優雅的方式,但同時也隱藏着一些問題,如:應用如何停止?對於傳統的部署在容器中的Java應用(非Spring Boot應用)可以使用容器提供的腳本優雅重啟,但是SpringBoot應用容器是內嵌的,也就不會存在容器的腳本,最直接的想法就是kill進程,但這樣很不優雅,進程強行終止會帶來數據丟失或者終端無法恢復到正常的狀態,在分布式環境下還可能導致數據不一致的情況。
SpringBoot提供了幾種停止的方法,本文重點介紹actuator endpoint的方法,SpringBoot官方文檔的Endpoints章節中介紹了應用發布生產准備的各種特性,其中通過Actuator的HTTP Endpoint,開發人員可以方便地對應用進行監控和管理。
簡易優雅停服
pom引入Maven依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
SpringBoot配置文件application.yml
server: port: 8077 management: endpoint: health: show-details: always shutdown: enabled: true endpoints: web: exposure: include: '*'
- management.endpoint.shutdown.enabled 這是說是否啟動/shutdown端點,默認是false,
- management.endpoints.web.exposure.include='*' 這是公開所有端點
測試Endpoint
按照上面進行配置后,SpringBoot項目就可以優雅關閉了,只要模擬一個POST請求,在Postman或者其他工具,訪問如下路徑
http://localhost:8077/actuator/shutdown
注:替換成自己項目的host及port,必須是post
返回
{ "message": "Shutting down, bye..." }
說明SpringBoot應用已優雅關閉
安全設置
雖然SpringBoot應用已可以優雅關閉了,但是還存在很大的安全隱患,如果有搞破壞的知道了ip、端口號后就可以模擬該請求停止服務了,因此需要增加一些安全限制
- management.endpoints.web.base-path 自定義shutdown的請求路徑
- management.server.address 設置為本地ip,就可以防止遠程訪問該連接進行關閉服務了
- management.server.port 自定義shutdown請求路徑的端口號
進行這些配置后就可以做到最基本的安全且優雅的關閉SpringBoot應用了,調整后的配置文件如下
Endpoint配置文件
management: endpoint: health: show-details: always shutdown: # 啟用shutdown配置 enabled: true endpoints: web: exposure: include: '*' # 自定義管理斷點的前綴,安全性考慮 base-path: /restartactuator server: # 自定義端口 port: 12581 # 不允許遠程管理連接,安全性考慮 address: 127.0.0.1
驗證
登錄到SpringBoot應用部署的服務器,本地通過curl執行POST請求
curl -X POST http://127.0.0.1:12581/restartactuator/shutdown
然后可以可到如下輸出
{"message":"Shutting down, bye..."}
說明SpringBoot應用已經優雅且安全的進行了停止
相關知識
kill指令
kill -9 pid 是不進行任何等待判斷,可以理解為操作系統從內核級別強行殺死某個進程,可模擬為系統宕機、系統斷點等特殊情況
kill -15 pid 是等待應用關閉,執行阻塞操作,有時候也會出現無法關閉應用的情況(線上理想情況,是bug就該追根溯源)