Spring Bootアプリケーションをシャットダウンする

1概要

Spring Boot Applicationのライフサイクルを管理することは、プロダクション対応システムにとって非常に重要です。 Springコンテナは、 ApplicationContext. の助けを借りて、すべてのBeanの作成、初期化、および破棄を処理します。

  • この記事の強調点はライフサイクルの破壊段階です。具体的には、Spring Bootアプリケーションをシャットダウンするさまざまな方法について説明します。

Spring Bootを使用してプロジェクトを設定する方法の詳細については、/spring-boot-starters[Spring Boot Starter]の記事を参照するか、またはリンク:/spring-boot-application-configuration[Spring Bootの設定]を参照してください。]。

2シャットダウンエンドポイント

デフォルトでは、Spring Boot Applicationでは /shutdown を除くすべてのエンドポイントが有効になっています。これは当然のことながら Actuator エンドポイントの一部です。

これを設定するためのMavenの依存関係は次のとおりです。

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

また、セキュリティサポートも設定したい場合は、以下が必要です。

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

最後に、 application.properties ファイルでシャットダウンエンドポイントを有効にします。

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

また、使用したいアクチュエータの端点も公開する必要があります。上の例では、 /shutdown エンドポイントを含むすべてのアクチュエータエンドポイントを公開しました。

  • Spring Bootアプリケーションをシャットダウンするには、このようにPOSTメソッドを呼び出します。

curl -X POST localhost:port/actuator/shutdown

この呼び出しでは、 port はアクチュエータポートを表します。

3.アプリケーションコンテキストを閉じる

アプリケーションコンテキストを使用して close() メソッドを直接呼び出すこともできます。

コンテキストを作成して閉じる例から始めましょう。

ConfigurableApplicationContext ctx = new
  SpringApplicationBuilder(Application.class).web(WebApplicationType.NONE).run();
System.out.println("Spring Boot application started");
ctx.getBean(TerminateBean.class);
ctx.close();
  • これにより、すべてのBeanが破棄され、ロックが解除されてからBeanファクトリが閉じられます** 。アプリケーションのシャットダウンを確認するために、 @ PreDestroy アノテーション付きのSpringの標準的なライフサイクルコールバックを使用します。

public class TerminateBean {

    @PreDestroy
    public void onDestroy() throws Exception {
        System.out.println("Spring Container is destroyed!");
    }
}

このタイプのBeanも追加する必要があります。

@Configuration
public class ShutdownConfig {

    @Bean
    public TerminateBean getTerminateBean() {
        return new TerminateBean();
    }
}

この例を実行した後の出力は次のとおりです。

Spring Boot application started
Closing[email protected]DefaultLifecycleProcessor - Stopping beans in phase 0
Unregistering JMX-exposed beans on shutdown
Spring Container is destroyed!

ここで留意しておくべき重要なことは、** アプリケーションのコンテキストを閉じるときに、ライフサイクルが異なるために親のコンテキストは影響を受けないことです。

3.1. 現在のアプリケーションコンテキストを閉じる

上記の例では、子アプリケーションコンテキストを作成してから close() メソッドを使用してそれを破棄しました。

現在のコンテキストを閉じたい場合、1つの解決策は単にアクチュエーター /shutdown エンドポイントを呼び出すことです。

ただし、独自のカスタムエンドポイントを作成することもできます。

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

    }
}

ここでは、 ApplicationContextAware インターフェースを実装し、現在のアプリケーションコンテキストを取得するためにsetterメソッドをオーバーライドするコントローラを追加しました。次に、マッピングメソッドでは、単に close() メソッドを呼び出します。

それから、新しいエンドポイントを呼び出して現在のコンテキストをシャットダウンできます。

curl -X POST localhost:port/shutdownContext

もちろん、実際のアプリケーションにこのようなエンドポイントを追加する場合は、それも保護する必要があります。

4.SpringApplication__を終了します

SpringApplication shutdown フックをJVMに登録して、アプリケーションが適切に終了するようにします。

Beanは、特定のエラーコードを返すために ExitCodeGenerator インタフェースを実装することができます。

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ラムダのアプリケーションと同じコード:

SpringApplication.exit(ctx, () -> 0);
  • System.exit(exitCode) を呼び出した後、プログラムは0の戻りコード** で終了します。

Process finished with exit code 0

5アプリプロセスを強制終了

最後に、bashスクリプトを使用して、Spring Boot Applicationをアプリケーションの外部からシャットダウンすることもできます。このオプションの最初のステップは、アプリケーションコンテキストにそれのPIDをファイルに書き込ませることです。

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)

shutdown.bat を実行すると、 shutdown.pid ファイルからプロセスIDが抽出され、 kill コマンドを使用してBootアプリケーションが終了します。

6. 結論

この記事では、実行中のSpring Bootアプリケーションをシャットダウンするために使用できるいくつかの簡単な方法について説明しました。

適切な方法を選択するのは開発者次第です。これらの方法はすべて、設計上および意図的に使用されるべきです。

たとえば、エラーコードを別の環境に渡す必要がある場合は .exit() が推奨されます(さらなるアクションのためにJVMなど)。 Application PID を使用すると、bashスクリプトを使用して アプリケーションを起動または再起動することもできるため、柔軟性が向上します。

最後に、 /shutdown は、HTTPを介して外部でアプリケーションを終了することを可能にするためのものです。他のすべてのケースでは .close() は完全に動作します。

いつものように、この記事の完全なコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot-ops[GitHubプロジェクト]にあります。