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

前言

在生產環境下管理Spring Boot應用的生命週期很是重要。Spring容器經過ApplicationContext處理應用服務的全部的beans的建立、初始化、銷燬。本文着重於生命週期中的銷燬階段的處理,我將使用多種方式來實現關閉Spring Boot應用服務。若是你須要瞭解關於Spring Boot更多內容,請看我以前寫過的文章和精品合輯!web

1、經過Actuator Shutdown 端點服務

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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>複製代碼

生產環境一般出於安全考慮,不能將應用關閉的訪問徹底公開,咱們還要引入spring-boot-starter-security。具體的安全配置,請參考學習Spring security,在此很少作敘述!shell

<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應用服務。springboot

curl -X POST localhost:port/actuator/shutdown複製代碼

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

2、 關閉Application Context

咱們也能夠本身實現一個Controller開放訪問端點,調用Application Context的close方法實現應用服務的關閉。curl

@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請求,實現應用的關閉。ide

curl -X POST localhost:port/shutdownContext複製代碼

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

4、退出 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);複製代碼

5、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)複製代碼

而後調用這個腳本就能夠把應用服務進程殺死。

期待您的關注

相關文章
相關標籤/搜索