第10章 Undertow

10.1. Undertow ハンドラーについて

Undertow は、ブロックタスクと非ブロックタスクの両方に使用するよう設計された Web サーバーです。JBoss EAP 7 では JBoss Web は Undertow に置き換わります。主な機能の一部は以下のとおりです。

  • ハイパフォーマンス
  • 組み込み可能
  • Servlet 4.0
  • Web ソケット
  • リバースプロキシー

リクエストライフサイクル

クライアントがサーバーに接続するときに、Undertow によって io.undertow.server.HttpServerConnection が作成されます。クライアントがリクエストを送信するときに、リクエストは Undertow パーサーによって解析され、生成される io.undertow.server.HttpServerExchange はルートハンドラーに渡されます。ルートハンドラーが完了すると、以下の 4 つのいずれかのことが起こります。

  • 交換が完了します。

    リクエストチャネルと応答チャネルが完全に読み取られたり、書き込まれた場合に、交換が完了したと見なされます。リクエスト側は、GET や HEAD などのコンテンツがないリクエストの場合に、自動的に完全に読み取られたと見なされます。読み取り側は、ハンドラーが完全な応答を書き込み、応答チャネルを閉じ、応答チャネルを完全にフラッシュしたときに、完了したと見なされます。交換がすでに完了した場合は、どんなアクションも行われません。

  • 交換を完了せずにルートハンドラーが通常どおり返されます。

    この場合、交換は HttpServerExchange.endExchange() を呼び出して完了します。

  • ルートハンドラーが例外で返されます。

    この場合、500 の応答コードが設定され、HttpServerExchange.endExchange() を使用して交換が終了します。

  • ルートハンドラーは、HttpServerExchange.dispatch() が呼び出された後、または非同期 IO が開始された後に返すことができます。

    この場合、ディスパッチされたタスクはディスパッチエグゼキューターに送信されます。また、非同期 IO がリクエストチャネルまたは応答チャネルのいずれかで開始された場合は、このタスクが開始されます。交換はどちらの場合でも完了しません。非同期タスクによって、処理が完了したときに交換が完了します。

HttpServerExchange.dispatch() の最も一般的な使用方法は、実行をブロッキングが許可されない IO スレッドから、ブロッキング操作を許可するワーカースレッドに移動することです。

例: ワーカースレッドへのディスパッチ

public void handleRequest(final HttpServerExchange exchange) throws Exception {
    if (exchange.isInIoThread()) {
      exchange.dispatch(this);
      return;
    }
    //handler code
}

交換は呼び出しスタックが返されるまで実際にはディスパッチされないため、交換で一度に複数のスレッドがアクティブにならないようにすることができます。交換はスレッドセーフではありません。ただし、交換は、両方のスレッドが 1 度に変更しようとしない限り、複数のスレッド間で渡すことができます。

交換の終了

交換を終了するには、リクエストチャネルを読み取り、応答チャネルで shutdownWrites() を呼び出し、フラッシュする方法と HttpServerExchange.endExchange() を呼び出す方法の 2 つがあります。endExchange() が呼び出された場合、Undertow はコンテンツが生成されたかどうかを確認します。生成された場合、Undertow はリクエストチャネルを単にドレインし、応答チャネルを閉じ、フラッシュします。生成されず、交換で登録されたデフォルトの応答リスナーがある場合は、Undertow によってそれらの各応答リスナーがデフォルトの応答を生成できるようになります。このメカニズムにより、デフォルトのエラーページが生成されます。

Undertow の設定に関する詳細は、JBoss EAP『設定ガイド』の「Web サーバーの設定」を参照してください。