SpringBoot生命周期管理之停掉應用服務幾種方法


前言

在生產環境下管理Spring Boot應用的生命周期非常重要。Spring容器通過ApplicationContext處理應用服務的所有的beans的創建、初始化、銷毀。
本文着重於生命周期中的銷毀階段的處理,我將使用多種方式來實現關閉Spring Boot應用服務。如果你需要了解關於Spring Boot更多內容,請看我之前寫過的文章和精品合輯!

一、通過Actuator Shutdown 端點服務

Spring Boot Actuator是一個主要用於應用指標監控和健康檢查的服務。可以通過Http訪問對應的Endpoint來獲取應用的健康及指標信息。另外,它還提供了一個遠程通過http實現應用shutdown的端點。
首先,我們要在Spring Boot中引入Actuator。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

生產環境通常出於安全考慮,不能將應用關閉的訪問完全公開,我們還要引入spring-boot-starter-security。具體的安全配置,請參考學習Spring security,在此不多做敘述!

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

默認情況下,出於安全考慮shutdown端點服務是處於關閉狀態的,我們需要通過配置開啟:

management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true
endpoints.shutdown.enabled=true

至此,我們就可以通過發送一個Post請求,來停掉Spring Boot應用服務。

curl -X POST localhost:port/actuator/shutdown

這種方法的缺陷在於:當你引入Actuator的shutdown服務的時候,其他的監控服務也自動被引入了。

二、 關閉Application Context

我們也可以自己實現一個Controller開放訪問端點,調用Application Context的close方法實現應用服務的關閉。

@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;
         
    }
}

我們添加了一個Controller繼承自ApplicationContextAware接口,並且重寫了setApplicationContext方法獲取當前的應用上下文。然后在Post請求方法中調用close方法關閉當前應用。這種實現的方法更加輕量級,不會像Actuator一樣引入更多的內容。我們同樣可以通過發送Post請求,實現應用的關閉。

curl -X POST localhost:port/shutdownContext

同樣,當你對外開放一個關閉服務的端點,你要考慮它的權限與安全性

四、退出 SpringApplication

還可以通過SpringApplication 向JVM注冊一個 shutdown 鈎子來確保應用服務正確的關閉。

ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class)
  .web(WebApplicationType.NONE).run();
 
int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
@Override
public int getExitCode() {
        // return the error code
        return 0;
    }
});
 
System.exit(exitCode);

同樣的效果,使用Java 8 lambda可以這樣實現,代碼簡單很多:

SpringApplication.exit(ctx, () -> 0);

五、kill殺掉應用進程

我們還可以使用bat或者shell腳本來停止應用的進程。所以,我們首先在應用啟動的時候,要把進程ID寫到一個文件里面。如下所示:

SpringApplicationBuilder app = new SpringApplicationBuilder(Application.class)
  .web(WebApplicationType.NONE);
app.build().addListeners(new ApplicationPidFileWriter("./bin/shutdown.pid"));
app.run();

創建一個shutdown.bat腳本,內容如下:

kill $(cat ./bin/shutdown.pid)

然后調用這個腳本就可以把應用服務進程殺死。

期待您的關注


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM