ドキュメント

§連携シャットダウン

PlayはPekkoの連携シャットダウン機能を組み込んでいますが、まだ完全に依存しているわけではありません。連携シャットダウンはPlayの完全なシャットダウンを担当しますが、`ApplicationLifecycle` APIはまだ存在しており、JVMの終了はPlayの責任です。

本番環境では、クリーンシャットダウンを呼び出すトリガーは`SIGTERM`、またはPlayプロセスがPekkoクラスタの一部である場合は`Downing`イベントになります。

**注意**: Playを組み込みで使用している場合、またはテストで`Application`と`Server`を手動で処理している場合、Play内部の連携シャットダウンへの移行は、連携シャットダウンを使用すると`Application`と`Server`の依存ライフサイクルに小さな変更が加えられるため、シャットダウンプロセスに影響を与える可能性があります。
1. `Server#stop`の呼び出しは、`Server`を停止する**必要**があり、その`Server`で実行されている`Application`も停止する**必要**があります。
2. `Application#stop`の呼び出しは、`Application`を停止する**必要**があり、アプリケーションが実行されている`Server`も停止する**場合**があります。

§`ApplicationLifecycle`と比較するとどうですか?

連携シャットダウンは、`ApplicationLifecycle`が停止フックを登録する単一の 방법 を提供するのに対し、タスクを登録できる複数のフェーズを提供します。従来の`ApplicationLifecycle`停止フックは、Playが実行順序を決定する一連の操作でした。連携シャットダウンは、有向非巡回グラフ(DAG)で編成されたフェーズのコレクションを使用し、単一フェーズ内のすべてのタスクが並列に実行されます。つまり、クリーンアップコードを`ApplicationLifecycle`から連携シャットダウンに移動した場合、コードを実行するフェーズも指定する必要があります。アプリケーションの明らかに無関係な部分がシャットダウンする順序をきめ細かく制御したい場合は、`ApplicationLifecycle`の代わりに連携シャットダウンを使用できます。たとえば、アプリケーションがダウンしていることを開いているWebSocket経由で通知したい場合は、`before-service-unbind`という名前のフェーズにタスクを登録し、そのタスクがWebSocketクライアントにシグナルメッセージを送信するようにすることができます。`before-service-unbind`は、サーバー接続が解除されるフェーズである`service-unbind`の前に発生することが保証されています。ただし、接続を解除しても、処理中のリクエストは完了できます。

PlayのDIは`CoordinatedShutdown`のインスタンスを公開します。`ApplicationLifecycle`から連携シャットダウンに移行する場合、`ApplicationLifecycle`のインスタンスの注入を要求した場所であればどこでも、`CoordinatedShutdown`のインスタンスを要求できるようになりました。

`CoordinatedShutdown`インスタンスは`ActorSystem`インスタンスにバインドされます。`Server`と`Application`が`ActorSystem`を共有する環境では、いずれかが停止すると`Server`と`Application`の両方が停止します。新しいセクションのPlayマニュアルの連携シャットダウン、またはPekkoの連携シャットダウンに関するリファレンスドキュメントで詳細を確認できます。

§シャットダウンシーケンス

連携シャットダウンは、有向非巡回グラフ(DAG)として編成されたデフォルトのフェーズのセットでリリースされます。新しいフェーズを作成し、デフォルト値を上書きして、既存のフェーズが自分のフェーズに依存するようにすることができます。Pekkoに付属し、デフォルトでPlayで使用される最も関連性の高いフェーズのリストを次に示します。

  before-service-unbind
  service-unbind
  service-requests-done
  service-stop
  // few cluster-related phases only meant for internal use
  before-actor-system-terminate
  actor-system-terminate

上記のリストは、デフォルトで実行される順序で関連するフェーズを示しています。この動作を変更するには、Pekkoドキュメントに従ってください。

連携シャットダウンタスクに移行しない`ApplicationLifecycle#stopHooks`は、作成の逆順に実行され、`service-stop`フェーズ中に`CoordinatedShutdown`内で実行されることに注意してください。つまり、連携シャットダウンはすべての`ApplicationLifecycle#stopHooks`を単一のタスクと見なします。連携シャットダウンを使用すると、シャットダウンタスクを別のフェーズで実行する柔軟性が得られます。`ApplicationLifecycle#stopHooks`を使用する現在のコードは問題ありませんが、その呼び出し方法とタイミングを見直してください。たとえば、定期的にデータベース操作を実行するアクターがある場合、そのアクターにはデータベース接続が必要です。2つの作成方法によっては、`service-stop`フェーズで発生する`ApplicationLifecycle#stopHook`でデータベース接続プールが閉じられる可能性がありますが、アクターは後で発生する`actor-system-terminate`フェーズで閉じられない場合があります。

クリーンアップコードを`service-stop`フェーズで実行することが使用法と一致する場合は、`ApplicationLifecycle#stopHooks`を引き続き使用してください。

連携シャットダウンタスクの使用を選択するには、`CoordinatedShutdown`インスタンスを注入し、以下の例のように`addTask`を使用する必要があります。

Scala
class ResourceAllocatingScalaClass @Inject() (cs: CoordinatedShutdown) {
  // Some resource allocation happens here: A connection
  // pool is created, some client library is started, ...
  val resources = Resources.allocate()

  // Register a shutdown task as soon as possible.
  cs.addTask(CoordinatedShutdown.PhaseServiceUnbind, "free-some-resource") { () => resources.release() }

  // ... some more code
}
Java
public class ResourceAllocatingJavaClass {

  private final Resources resources;

  @Inject
  public ResourceAllocatingJavaClass(CoordinatedShutdown cs) {

    // Some resource allocation happens here: A connection
    // pool is created, some client library is started, ...
    resources = Resources.allocate();

    // Register a shutdown task as soon as possible.
    cs.addTask(
        CoordinatedShutdown.PhaseServiceUnbind(), "free-some-resource", () -> resources.release());
  }

  // ... some more code
}

§シャットダウントリガー

Playプロセスは通常、`SIGTERM`シグナルを介して終了されます。Playプロセスがシグナルを受信すると、JVMシャットダウンフックが実行され、連携シャットダウンの呼び出しによってサーバーが停止します。

他の考えられるトリガーは`SIGTERM`とは少し異なります。`SIGTERM`は外部から内部への方法で処理されますが、コードからシャットダウンをトリガーすることもできます(または、ライブラリがシャットダウンをトリガーする原因を検出する可能性があります)。たとえば、PlayプロセスをPekkoクラスタの一部として実行する場合、または管理者またはオーケストレーターがプログラムによるシャットダウンをトリガーできるエンドポイントをAPIに追加する場合などです。これらのシナリオでは、シャットダウンは内部から外部へです。連携シャットダウンリストのすべてのフェーズは適切な順序で実行されますが、アクターシステムはJVMシャットダウンフックが実行される前に終了します.

Playアプリケーションを開発する際には、すべての終了トリガーと、どの手順がどの順序で実行されるかを考慮する必要があります。

§制限事項

Pekko連携シャットダウンには、非常に設定可能な設定がいくつか付属しています。それにもかかわらず、Playライフサイクル内でPekko連携シャットダウンを使用すると、これらの設定の一部が無効になります。このような設定の1つは`pekko.coordinated-shutdown.exit-jvm`です。Playプロジェクトで`pekko.coordinated-shutdown.exit-jvm`を有効にすると、シャットダウン時にデッドロックが発生し、プロセスが完了できなくなります。一般に、Pekko連携シャットダウンを調整するデフォルト値は、すべての本番、開発、およびテストモードで問題ありません。

§サーバーを正常にシャットダウンする

サーバーバックエンドのシャットダウンは正常に行われ、Pekko HTTPドキュメントに記載されている手順に従います。以下の概要はPekko HTTPサーバーバックエンドに適用されますが、PlayはNettyサーバーバックエンドをセットアップして、できるだけこれらの手順に従います。

  1. まず、サーバーポートはバインド解除され、新しい接続は受け入れられません(Nettyバックエンドにも適用されます)。
  2. リクエストが「処理中」(ユーザーコードによって処理されている)の場合、完了までに厳しい期限が設けられます。Pekko HTTPとNettyバックエンドの両方で、`play.server.terminationTimeout`を使用して期限を設定できます(詳細については、Pekko HTTP設定またはNetty設定の一般的なサーバー設定を参照してください)。
  3. 接続に「処理中」のリクエストがない場合、接続はすぐに終了します。
  4. ユーザーコードがタイムアウト内にレスポンスを送信した場合、このレスポンスは`Connection: close`ヘッダー付きでクライアントに送信され、接続は閉じられます。
  5. ストリーミングレスポンスの場合、期限内に完了する必要があるとされています。完了しない場合、ストリーミングレスポンスの状態に関係なく接続は終了します。
    注意: Pekko HTTP には、正常な終了中にレスポンスエンティティストリームが考慮されない バグ があります。回避策として、play.server.waitBeforeTermination に適切な遅延を設定して、これらのレスポンスが完了するまでの時間を確保できます。この設定の詳細については、Pekko HTTP 設定 または Netty 設定 の一般的なサーバー設定を参照してください。
  6. ユーザーコードが期限内にレスポンスを返さない場合、pekko.http.server.termination-deadline-exceeded-response で設定されたステータスを持つ自動レスポンスが送信されます。値は有効な HTTP ステータスコード である必要があります。

次: Pekko Typed & Cluster Sharding との統合


このドキュメントに誤りを見つけましたか?このページのソースコードは こちら にあります。ドキュメントガイドライン を読んだ後、プルリクエストを送信してください。質問やアドバイスがあれば、コミュニティフォーラム にアクセスして、コミュニティとの会話を始めてください。