こんにちは。
日本マイクロソフト、CSS デベロッパー ツールズ AppPlat の神田一行です。
今回は IIS に古くから存在する ISAPI モジュールと IIS 8.0 で標準搭載された Application Initializationを組み合わせて利用した際に発生する可能性があるトラブルについて、お伝えさせていただきます。
Application Initialization について
IIS は、既定でサービス開始直後にワーカープロセスを起動しません。ユーザーからのリクエストを受けてからワーカープロセスを起動し、その中で ASP.NET の初期処理などを行っています。結果、最初にリクエストを行うユーザーは、通常時と比べて応答に時間がかかる (初期化が完了するまで待たされる) こととなります。
この初回リクエストにかかるコストを軽減するための機能として Application Initialization が提供されており、自動的にワーカープロセスを起動させる機能と、仮想的な要求を内部的に発行し、該当の初期化処理を事前に終わらせる機能、の組み合わせで実現されています。
症状
IIS 上にホストしたページにアクセスした際、ブラウザーからの応答が無くなる、もしくは、503 Service Unavailable エラーが表示されます。
また、IIS サーバー上のイベントログに以下の様なログが繰り返し記録されます。
条件
本事象は、次の条件を全て満たすことで発生します。
- Windows Server 2012 から標準機能として搭載された Application Initialization を役割サービスから有効にする
- Web サイトやアプリケーションの詳細設定において、”有効化されたプリロード” が True となっている
- 処理の過程で “UNENCODED_URL” サーバー変数を参照する ISAPI モジュールを IIS にインストールする
原因
ApplicationInitialization が行う仮想的な要求は、初期化処理が完了するのに必要最低限の情報が設定されています。ただ、UNENCODED_URL を取得するには情報が不足しており、ワーカープロセスの異常終了に至ります。
DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK pecb) { .... pecb->GetServerVariable(hConn, "PRELOAD_REQUEST", lpvBuffer, lpdwSizeofBuffer); ....
ラピッドフェール保護が有効な環境 (デフォルト有効) では、短い期間で異常終了が繰り返す結果、アプリケーションプールが無効化された結果 503 Service Unavailable エラー発生します(通常ブラウザー上に 503 Service Unavailable が表示されます)。また、ラピッドフェール保護が無効な環境では、ブラウザーからの接続が切れるまで、IIS サーバー上においてワーカープロセスの異常終了が繰り返し発生します。
回避方法
以下2つの対処方法は、それぞれ独立した回避方法です。
- Web サイトやアプリケーションの詳細設定において、”有効化されたプリロード” を False にする
- GetServerVariable 関数の第二引数に対し “HTTP_USER_AGENT” を指定してユーザーエージェントを取得し、その値が “IIS Application Initialization Preload” であった場合は、処理をスキップする
本事象は開発部署も認識しており、将来のバージョンで修正を行う予定です。ただ、現バージョンにおいては、”回避方法” に記載させていただいた方法にて事象の回避をご検討ください。