ASP.NET アプリケーションから Web サービス要求を行うと、競合、パフォーマンスの低下、およびデッドロックが発生する

現象
ASP.NET アプリケーションから XML Web サービスに対する呼び出しを行うと、競合、パフォーマンスの低下、およびデッドロックが発生する場合があります。要求が応答を停止 (「ハング」) したことがクライアントから通知されることや、実行に時間がかかることがあります。デッドロックの可能性がある場合は、ワーカー プロセスが再利用されている可能性があります。アプリケーション イベント ログに、以下のメッセージが出力されることがあります。
  • Microsoft インターネット インフォメーション サービス (IIS) 5.0 を使用している場合、アプリケーション イベント ログに次のメッセージが出力されます。

       種類: エラーイベント ソース: ASP.NET 1.0.3705.0イベント カテゴリ: Noneイベント ID:        1003日付:            5/4/2003時刻: 18:18:23ユーザー: 該当なしコンピューター: <ComputerName>説明: デッドロック状態である可能性があるため、aspnet_wp.exe (PID: <xxx>) が繰り返されました。この 180 秒間に保留中の要求に対して応答は何も送信されていません。

  • IIS 6.0 を使用している場合、アプリケーション イベント ログに次のメッセージが出力されます。

       種類: Warningイベント ソース: W3SVC-WPイベント カテゴリ: Noneイベント ID:        2262日付:            5/4/2003時刻: 13:02:33ユーザー: 該当なしコンピューター: <ComputerName>説明: 次の理由のため、ISAPI 'C:\Windows\Microsoft.net\Framework\v.1.1.4322\aspnet_isapi.dll' は自身が危険な状況であると報告しました: 'デッドロックが検出されました'。

  • IIS 6.0 を使用している場合、システム イベント ログに次のメッセージが出力されます。

       種類: Warningイベント ソース: W3SVCイベント カテゴリ: Noneイベント ID:        1013日付:            5/4/2003時刻: 13:03:47ユーザー: 該当なしコンピューター: <ComputerName>説明: アプリケーション プール 'DefaultAppPool' を提供しているプロセスはシャットダウンの最中に時間制限を超えました。プロセス id は '<xxxx>' でした。

HttpWebRequest.GetResponse メソッドに対する呼び出しを実行すると、次の例外エラー メッセージも表示されることがあります。
“System.InvalidOperationException: 操作を完了するために十分なフリー スレッドが ThreadPool オブジェクトにありませんでした。
ブラウザーに、次の例外エラー メッセージが表示されることもあります。
“HttpException (0x80004005): 要求がタイムアウトしました”
: また、この資料の内容は、HttpWebRequest 要求を直接行うアプリケーションにも適用されます。
原因
この問題は、ASP.NET で、呼び出しが要求の実行に使用するワーカー スレッドと完了ポート スレッドの数が制限されているために発生することがあります。

通常、Web サービスに対する呼び出しでは、要求を送信するコードの実行に 1 つのワーカー スレッドを使用し、Web サービスからのコールバックの受信に 1 つの完了ポート スレッドを使用します。ただし、要求がリダイレクトされた場合や、認証が必要な場合は、呼び出しで 2 つのワーカー スレッドと 2 つの完了ポート スレッドが使用されることがあります。そのため、複数の Web サービス呼び出しが同時に発生すると、管理されている ThreadPool が枯渇する可能性があります。

たとえば、ThreadPool のワーカー スレッド数が 10 に制限されていて、10 個のすべてのワーカー スレッドで、コールバックの実行を待機するコードを実行中であるとします。この場合、ThreadPool のキューに格納されている作業項目はすべて、スレッドが使用可能になるまでブロックされるため、コールバックは実行できません。

競合の原因としてもう 1 つ考えられるのは、接続数を制限するために System.Net 名前空間が使用する maxconnection パラメーターです。通常は、この制限は正常に機能します。しかし、多くのアプリケーションが単一の IP アドレスに対して多数の要求を同時に実行すると、接続が使用可能になるまでスレッドが待機することが必要な場合もあります。
解決方法
これらの問題を解決するには、状況に応じて Machine.config ファイル内の以下のパラメーターを調整します。
  • maxWorkerThreads
  • minWorkerThreads
  • maxIoThreads
  • minFreeThreads
  • minLocalRequestFreeThreads
  • maxconnection
  • executionTimeout
これらの問題を適切に解決するには、次の手順を実行します。
  • 同時に実行できる ASP.NET 要求の数を、1 CPU あたり 12 個程度に制限します。
  • Web サービスのコールバックが ThreadPool 内のスレッドを自由に使用することを許可します。
  • maxconnections パラメーターの適切な値を選択します。この値は、使用する IP アドレスと AppDomains の数に基づいて選択します。
: ASP.NET 要求の数を 1 CPU あたり 12 個に制限するという推奨事項は、正確な計算に基づくものではありません。ただし、この制限に従うと、ほとんどのアプリケーションが良好に動作することが実証されています。

maxWorkerThreads および maxIoThreads

ASP.NET では、次の構成設定を使用して、使用するワーカー スレッドと完了スレッドの最大数を制限します。
<processModel maxWorkerThreads="20" maxIoThreads="20">
maxWorkerThreads パラメーターと maxIoThreads パラメーターには、暗黙的に CPU の数が掛けられます。たとえば、2 つのプロセッサがある場合、ワーカー スレッドの最大数は次のようになります。
2*maxWorkerThreads

minFreeThreads および minLocalRequestFreeThreads

また、ASP.NET では、次の構成設定で、リモート要求またはローカル要求を開始するために必要なワーカー スレッドと完了ポート スレッドの数が決まります。
<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">
使用可能なスレッドが十分にない場合、要求を実行するのに十分なスレッドが解放されるまで、要求はキューに格納されます。そのため、ASP.NET では、次の個数を超える要求は同時に実行されません。
(maxWorkerThreads*number of CPUs)-minFreeThreads
: minFreeThreads パラメーターと minLocalRequestFreeThreads パラメーターには、暗黙的に CPU の数が掛けられることはありません。

minWorkerThreads

ASP.NET 1.0 Service Pack 3 および ASP.NET 1.1, ASP.NET では、次の構成設定で、リモート要求の処理にすぐに使用できるワーカー スレッドの数が決まります。
<processModel minWorkerThreads="1">
この設定によって制御されるスレッドは、CLR の既定の「スレッド チューニング」機能によって作成されるワーカー スレッドより速く作成できます。この設定を使用すると、ASP.NET で、バック エンド サーバーのパフォーマンス低下、クライアント側からの要求の急激な増加、またはキュー内の要求数の急激な増加をもたらす他の同様の原因によって急激に ASP.NET の要求キューにたまる要求を処理できます。minWorkerThreads パラメーターの既定値は 1 です。minWorkerThreads パラメーターの値は、以下の値に設定することができます。
minWorkerThreads = maxWorkerThreads / 2
minWorkerThreadsパラメーターは、既定では Web.config ファイルまたは Machine.config ファイルに存在しません。この設定には、暗黙的に CPU の数が掛けられます。

maxconnection

The maxconnection パラメーターには、特定の IP アドレスに対して確立できる接続の数を指定します。このパラメーターの例を以下に示します。
<connectionManagement><add address="*" maxconnection="2"><add address="65.53.32.230" maxconnection="12"></connectionManagement>
この資料でここまでに説明したパラメーターの設定は、すべてプロセス レベルです。ただし、maxconnection パラメーターの設定は、AppDomain レベルに適用されます。既定では、この設定は AppDomain レベルに適用されるため、プロセス内の各 AppDomain から特定の IP アドレスに対して最大 2 つの接続を作成できます。

executionTimeout

ASP.NET では、次の構成設定を使用して、要求の実行時間を制限します。
<httpRuntime executionTimeout="90"/>
この制限は、Server.ScriptTimeout プロパティを使用して設定することもできます。

: executionTimeout パラメーターの値を大きくすると、processModel responseDeadlockInterval パラメーターの設定の修正も必要となる場合があります。

推奨事項

ここに示す推奨設定は、すべてのアプリケーションで有効であるとは限りません。ただし、以下の追加情報を参照して、適切な設定に調整できる場合もあります。

各 ASPX ページから単一の IP アドレスに対して 1 つの Web サービス呼び出しを実行する場合は、次の構成設定を使用することをお勧めします。
  • maxWorkerThreads パラメーターと maxIoThreads パラメーターの値を 100 に設定します。
  • maxconnection パラメーターの値を 12*N に設定します(N は使用する CPU の数です)。
  • minFreeThreads パラメーターの値を 88*N に設定し、minLocalRequestFreeThreads パラメーターの値を 76*N に設定します。
  • minWorkerThreads の値を 50 に設定します。既定では、minWorkerThreads の値は構成ファイルに存在しません。そのため、この設定を追加する必要があります。
これらの一部の推奨値には、サーバーの CPU 数に関する簡単な計算式が適用されます。計算式で、CPU の数を表す変数は N で示されます。このような設定で、ハイパー スレッディングが有効になっている場合は、物理 CPU の数ではなく、論理 CPU の数を使用する必要があります。たとえば、ハイパー スレッディングが有効になっている 4 プロセッサのサーバーの場合、計算式の N は、4 ではなく 8 になります。

: この構成を使用すると、100-88=12 であるため、1 CPU あたり最大 12 個の ASP.NET 要求を同時に実行できます。したがって、少なくとも 88*N 個のワーカー スレッドと 88*N 個の完全ポート スレッドを別の用途 (Web サービスのコールバックなど) に使用できます。

たとえば、プロセッサが 4 台でハイパー スレッディングが有効になっているサーバーがあるとします。上記の計算式に基づき、この資料に記載されている構成設定には、以下の値を使用します。
<system.web>	<processModel maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50"/>	<httpRuntime minFreeThreads="704" minLocalRequestFreeThreads="608"/></system.web><system.net>	<connectionManagement>		<add address="[ProvideIPHere]" maxconnection="96"/>	</connectionManagement></system.net>

また、この構成を使用すると、各 AppDomain で 1 つの IP アドレスに対して 1 CPU あたり 12 個の接続を使用できます。したがって、以下の場合、要求が接続を待機している間に競合が発生することはほとんどなく、ThreadPool が枯渇することはありません。
  • Web ホストで 1 つのアプリケーション (AppDomain) のみをホストする。
  • ASPX ページの各要求が 1 つの Web サービス要求を行う。
  • すべての要求が同じ IP アドレスに対して行われる。
ただし、この構成を使用すると、次のいずれかに該当する場合、接続が過剰に使用される可能性があります。
  • 要求が複数の IP アドレスに対して行われる。
  • 要求がリダイレクトされる (302 状態コード)。
  • 要求に認証が必要とされる。
  • 要求が複数の AppDomains から実行される。
このような場合、maxconnection パラメーターには小さい値を使用し、minFreeThreads パラメーターと minLocalRequestFreeThreads パラメーターには大きい値を使用することをお勧めします。
状況
この動作は仕様です。
詳細
ASP.NET による IIS 7.0 でパフォーマンスの低下や競合が発生している場合は、次のマイクロソフトのブログを参照してください。

ASP.NET Thread Usage on IIS 7.0 and 6.0
ASP.net Hang in IIS 7.0
関連情報
詳細については、次の MSDN (Microsoft Developer Network) Web サイトを参照してください。
プロパティ

文書番号:821268 - 最終更新日: 12/17/2009 16:17:36 - リビジョン: 11.0

Microsoft .NET Framework 2.0, Microsoft ASP.NET 1.1, Microsoft ASP.NET 1.0

  • kbprb KB821268
フィードバック