HTTPリクエストのライフサイクル
必要な依存関係: io.ktor:ktor-server-core
コード例: server-http-request-lifecycle
サポートされているエンジン: Netty, CIO
デフォルトでは、Ktorはクライアントが切断された場合でもリクエストの処理を継続します。 HttpRequestLifecycle プラグインを使用すると、クライアントが切断されるとすぐにリクエスト処理をキャンセルできます。
これは、クライアントが応答を待たなくなったときに実行を停止すべき、長時間実行されるリクエストやリソースを大量に消費するリクエストに役立ちます。
HttpRequestLifecycleのインストールと設定
HttpRequestLifecycleプラグインを有効にするには、install関数を使用してアプリケーションモジュールにインストールし、cancelCallOnCloseプロパティを設定します。
import io.ktor.server.application.*
import io.ktor.server.http.HttpRequestLifecycle
fun Application.module() {
install(HttpRequestLifecycle) {
cancelCallOnClose = true
}
}cancelCallOnCloseプロパティが有効になると、HttpRequestLifecycleプラグインはリクエストごとにキャンセルハンドラーをインストールします。クライアントが切断されると、その特定のルートを処理しているコルーチンのみがキャンセルされます。
キャンセルは構造化された並行性(structured concurrency)を通じて伝播するため、リクエストコルーチンから開始されたすべての子コルーチン(たとえば、launchやasyncを使用したもの)もキャンセルされます。次のサスペンションポイント(中断点)でCancellationExceptionがスローされます。
キャンセルの処理
CancellationExceptionをキャッチして、リソースの解放やバックグラウンド作業の停止などのクリーンアップ操作を実行できます。
fun Application.module() {
install(HttpRequestLifecycle) {
cancelCallOnClose = true
}
routing {
get("/long-process") {
try {
while (isActive) {
delay(10_000)
log.info("Very important work.")
}
call.respond("Completed")
} catch (e: CancellationException) {
log.info("Cleaning up resources.")
}
}
}
}コルーチンのキャンセルは協調的(cooperative)です。ブロッキングコードやCPU負荷の高いコードは自動的には中断されません。 リクエスト処理で長時間実行される作業を行う場合は、
call.coroutineContext.ensureActive()を呼び出してキャンセルに対応してください。詳細については、 コルーチンのキャンセルを参照してください。
完全な例については、server-http-request-lifecycleを参照してください。
制限事項
このプラグインは、CIOおよびNettyエンジンでのみ完全にサポートされています。サーブレットベースのエンジン(またはその他のサポートされていないエンジン)では、クライアントの切断を確実に検出できません。キャンセルは、サーバーがレスポンスを書き込もうとしたときにのみ検出されます。
