Spring Boot: 實現優雅退出
2018.11.18
文章目錄
前言
要求某個基於Spring Boot的排程器,能實現優雅退出,使得退出時正在執行時的作業能進行必要的回滾操作。為此,翻譯某技術部落格的總結1。
方法
每個Spring應用都會在JVM裡註冊一個shutdown hook1
方法一:Actuator的Endpoint機制1
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
預設配置下,shutdown
端點是關閉的,需要在application.properties
裡配置:
management.endpoint.shutdown.enabled=true
Actuator的端點,支援通過JMX或HTTP進行遠端訪問。而shutdown
預設配置下是不支援HTTP進行Web訪問的,所以使用HTTP請求進行關閉,還需要配置:
management.endpoints.web.exposure.include=shutdown
最後,配合使用對應的URL就能讓Spring Boot應用優雅退出:
curl -X POST localhost:port/actuator/shutdown
方法二:使用ApplicationContext#close()
方法
ApplicationContext#close()
亦能實現優雅退出,但要使得當前application context退出,就需要一個入口,從外部接收到退出的訊號。一種方法就是上述的Endpoint端點,另一種方法適用於Spring MVC的Web應用,就是定製一個Controller實現ApplicationContextAware
@RestController
public class ShutdownController implements ApplicationContextAware {
private ApplicationContext context;
@PostMapping("/shutdownContext")
public void shutdownContext() {
((ConfigurableApplicationContext) context).close();
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.context = ctx;
}
}
同樣地,配合使用對應的URL就能讓Spring Boot應用優雅退出:
curl -X POST localhost:port/shutdownContext
方法三:@PreDestroy
+ kill <pid>
如果專案不是Spring MVC,又不想引入Actuator,可以直接採用ctrl + c或kill <pid>
的方式。因為Spring應用在JVM裡註冊了一個shutdown hook,所以只要能接收到退出的訊號(ctrl + c或kill <pid>
,而kill -9 <pid>
不行),那麼應用就能正常地優雅退出。如果專案是通過nohup java -jar project.jar &
方式啟動的,那麼就建議使用kill <pid>
命令,給應用傳送一個TERM
訊號,就能正常優雅退出。@PreDestroy
註解允許方法完成必要的退出工作。
獲取pid的方式可使用如下兩種:
- Bash shell
ps -ef | grep project.jar | awk '{print $2}'
- Java程式碼
SpringApplicationBuilder app = new SpringApplicationBuilder(Application.class).web(WebApplicationType.NONE);
app.build().addListeners(new ApplicationPidFileWriter("./bin/shutdown.pid"));
app.run();
Actuator Endpoints
Actuator提供了Endpoint端點,可能用於對Spring Boot應用進行監控和互動。其中有一個shutdown
端點,就是用於優雅退出的。使用Actuator的端點,首先需要配置Actuator相關依賴2: ↩︎