? Spring Boot 依賴與配置
Maven 依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.github.timpeeters</groupId>
<artifactId>spring-boot-graceful-shutdown</artifactId>
<version>2.1.1</version>
</dependency>
? Graceful Shutdown 配置說明
配置項 | 默認值 | 描述 |
---|---|---|
graceful.shutdown.enabled | false | 是否啟用優雅停機 |
graceful.shutdown.timeout | 60 | 在關閉 Tomcat Connector 之前等待活躍線程完成的秒數 |
graceful.shutdown.wait | 30 | 優雅停機前,服務處于 OUT_OF_SERVICE 的時間 |
? Graceful Shutdown 流程
- JVM 接受 SIGTERM 信號,開始關閉 Spring Container
- Spring EventListener 監聽 ContextClosedEvent 事件,關閉開始后回調
- EventListener 更新 Spring Boot HealthIndicator 為 "OUT_OF_SERVICE"
- 使用 Thread.sleep 延遲 Context 關閉,以便負載均衡器查看更新的 HealthIndicator 狀態,并停止向此實例轉發請求
- 當 Thread.sleep 結束, Tomcat container 正常關閉。首先通過暫停 Connector,不再接受新的請求,然后通過配置的時間讓 Tomcat 線程池處理活躍的線程
- 最后, Spring Context 關閉
? Github Demo URL
示例中,Spring Boot 配置如下:
graceful.shutdown.enabled=true
graceful.shutdown.timeout=60s
graceful.shutdown.wait=30s
正常運行時,執行 curl http://127.0.0.1:8080/actuator/health
,結果如下:
{
"status": "UP"
}
關閉服務后,30 秒內,執行 curl http://127.0.0.1:8080/actuator/health
,結果如下:
{
"status": "OUT_OF_SERVICE"
}
30 秒內,服務能正常接收新的請求。30 秒后,服務不再接受新的請求,會有如下幾種情況:
- Tomcat 無請求待處理,服務立即關閉
- Tomcat 有請求待處理,處理時間在 60 秒內,服務會在所有請求處理完后立即關閉
- Tomcat 有請求待處理,處理時間超過 60 秒,服務會在 60 秒后強制關閉,異常退出