48

ASP.NETMVCのAsyncControllersについて読んでいます。

それらが存在する唯一の理由は、IISスレッドを保存できる一方で、長時間実行される作業が通常のCLRスレッドに委任されるためであると思われます。

ここにいくつか質問があります:

  • 非同期コントローラーをサポートするように構築されたこのアーキテクチャ全体を正当化するために、これらのIISスレッドが非常に高価なのはなぜですか?
  • IISアプリケーションプールで実行されているIISスレッドの数を確認/構成するにはどうすればよいですか?
4

4 に答える 4

53

ASP.NETは、.NETスレッドプールのスレッドを使用して要求を処理します。スレッドプールは、スレッドの初期化コストがすでに発生しているスレッドのプールを維持します。したがって、これらのスレッドは簡単に再利用できます。.NETスレッドプールもセルフチューニングです。CPUおよびその他のリソース使用率を監視し、必要に応じて新しいスレッドを追加したり、スレッドプールのサイズを調整したりします。通常、作業を実行するために手動でスレッドを作成することは避けてください。代わりに、スレッドプールのスレッドを使用してください。同時に、アプリケーションが長時間のブロッキング操作を実行しないようにすることが重要です。これにより、スレッドプールの枯渇やHTTPリクエストの拒否がすぐに発生する可能性があります。

ディスクI/O、Webサービス呼び出しはすべてブロックされています。非同期呼び出しを使用して最適化するのが最適です。非同期呼び出しを行うと、asp.netはスレッドを解放し、コールバック関数が呼び出されたときに要求が別のスレッドに割り当てられます。

設定できるスレッド数を構成するには、次のようにします。

<system.web>
    <applicationPool maxConcurrentRequestsPerCPU="50" maxConcurrentThreadsPerCPU="0" requestQueueLimit="5000"/>
</system.web>

参照:IIS 7.5、IIS 7.0、およびIIS6.0でのASP.NETスレッドの使用

これらは、Microsoftのベストプラクティスが推奨する設定です。

  • maxconnectionを12*CPUの数に設定します。この設定は、クライアントから開始できる発信HTTP接続の最大数を制御します。この場合、ASP.NETがクライアントです。maxconnectionを12*CPUの数に設定します。
  • maxIoThreadsを100に設定します。この設定は、.NETスレッドプール内のI/Oスレッドの最大数を制御します。この数は、使用可能なCPUの数で自動的に乗算されます。maxloThreadsを100に設定します。
  • maxWorkerThreadsを100に設定します。この設定は、スレッドプール内のワーカースレッドの最大数を制御します。この数は、使用可能なCPUの数で自動的に乗算されます。maxWorkerThreadsを100に設定します。
  • minFreeThreadsを88*CPUの数に設定します。この設定は、スレッドプールで使用可能なスレッドの数がこの設定の値を下回った場合に、すべての着信要求をキューに入れるためにワーカープロセスによって使用されます。この設定により、同時に実行できるリクエストの数がmaxWorkerThreads(minFreeThreads)に効果的に制限されます。minFreeThreadsを88*CPUの数に設定します。これにより、同時リクエストの数が12に制限されます(maxWorkerThreadsが100であると想定)。
  • minLocalRequestFreeThreadsを76*CPUの数に設定します。この設定は、スレッドプールで使用可能なスレッドの数がこの数を下回った場合に、ローカルホスト(WebアプリケーションがローカルWebサービスに要求を送信する場所)からの要求をキューに入れるためにワーカープロセスによって使用されます。この設定はminFreeThreadsに似ていますが、ローカルコンピューターからのローカルホスト要求にのみ適用されます。minLocalRequestFreeThreadsを76*CPUの数に設定します。

:このセクションで提供される推奨事項はルールではありません。それらは出発点です。

アプリケーションに最適なものを見つけるには、アプリケーションのベンチマークを行う必要があります。

于 2012-09-06T18:10:37.130 に答える
6

IISスレッドは、デフォルトのスレッドプールから取得されます。これは、プロセッサコアの数に基づいてデフォルトで制限されています。このスレッドプールキューがバックアップされると、IISは要求への応答を停止します。非同期コードを使用することにより、非同期操作の実行中にスレッドプールスレッドをプールに戻すことができるため、IISは全体としてより多くの要求を処理できます。

一方、自分で新しいスレッドを生成することは、スレッドプールスレッドを利用しません。チェックされていない数の独立したスレッドを生成することも問題になる可能性があるため、IISスレッドプールの問題をすべて解決できるわけではありません。通常、非同期IOがどちらの方法でも推奨されます。

スレッドプール内のスレッド数の変更については、こちらを確認してください。ただし、おそらくそうすることは避けてください。

于 2012-09-06T17:00:00.507 に答える
5

私たちのWebサービスは時々 100レケ/秒を提供する必要がありますが、それ以外の時間は1リクエスト/秒です。Analazyng IISログでは、バーストが発生してそのような呼び出しを処理するのに約28秒かかることがわかりました。

@nunespascalで引用されているMicrosoftのベストプラクティスを適用すると、この場合、時間が1秒に大幅に短縮されました。

以下は、運用サーバーを展開するときに現在使用しているPowershellスクリプトです。論理プロセッサ番号をカウントしてmachine.configを更新します。

<# Get and backup current machine.config #>
$path = "C:\Windows\Microsoft.Net\Framework\v4.0.30319\Config\machine.config";
$xml = [xml] (get-content($path));
$xml.Save($path + "-" + (Get-Date -Format "yyyyMMdd-HHmm" ) + ".bak");

<# Get number of physical CPU #>
$physicalCPUs = ([ARRAY](Get-WmiObject Win32_Processor)).Count;

<# Get number of logical processors #>
$logicalProcessors = (([ARRAY](Get-WmiObject Win32_Processor))[0] | Select-Object “numberOfLogicalProcessors").numberOfLogicalProcessors * $physicalCPUs;

<# Set Number of connection in system.net/connectionManagement #>
$systemNet =  $xml.configuration["system.net"];
if (-not $systemNet){
    $systemNet = $xml.configuration.AppendChild($xml.CreateElement("system.net"));
}

$connectionManagement = $systemNet.connectionManagement;
if (-not $connectionManagement){

    $connectionManagement = $systemNet.AppendChild($xml.CreateElement("connectionManagement"));
}

$add = $connectionManagement.add;
if(-not $add){
    $add = $connectionManagement.AppendChild($xml.CreateElement("add")) ;
}
$add.SetAttribute("address","*");
$add.SetAttribute("maxconnection", [string]($logicalProcessors * 12) );

<# Set several thread settings in system.web/processModel #>
$systemWeb =  $xml.configuration["system.web"];
if (-not $systemWeb){
    $systemWeb = $xml.configuration.AppendChild($xml.CreateElement("system.web"));
}

$processModel = $systemWeb.processModel;
if (-not $processModel){
    $processModel = $systemWeb.AppendChild($xml.CreateElement("processModel"));
}
$processModel.SetAttribute("autoConfig","true");
$processModel.SetAttribute("maxWorkerThreads","100");
$processModel.SetAttribute("maxIoThreads","100");
$processModel.SetAttribute("minWorkerThreads","50");
$processModel.SetAttribute("minIoThreads","50");

<# Set other thread settings in system.web/httRuntime #>
$httpRuntime = $systemWeb.httpRuntime;
if(-not $httpRuntime){
    $httpRuntime = $systemWeb.AppendChild($xml.CreateElement("httpRuntime"));
}
$httpRuntime.SetAttribute("minFreeThreads",[string]($logicalProcessors * 88));
$httpRuntime.SetAttribute("minLocalRequestFreeThreads",[string]($logicalProcessors * 76));

<#Save modified machine.config#>
$xml.Save($path);

このソリューションは、2009年にStuartBrierleyが執筆したブログ記事から得られました。2008R2から2016までWindowsServerでテストに成功しました。

于 2017-05-17T09:57:48.280 に答える
4

実際、あなたがリンクした記事に書かれていることは真実ではありません。非同期パターンは、「非常に高価なIISワーカースレッド」を解放し、バックグラウンドで他の「安価なスレッド」を使用するためのものではありません。

非同期パターンは、単にスレッドを解放するためのものです。スレッドを必要としない(そしてローカルマシンを必要としない)シナリオでは、このメリットを享受できます。

2つのシナリオ例(両方ともI / O)を挙げられます。

初め:

  1. BeginRequest
  2. 非同期ファイルの読み取りを開始します
  3. ファイルの読み取り中はスレッドは必要ないため、他のリクエストで使用できます。
  4. ファイルの読み取りが終了します-アプリプールからスレッドを取得します。
  5. リクエストが終了します。

そしてほぼ同じ秒:

  1. BeginRequest
  2. WCFサービスへの非同期呼び出しを開始します。
  3. マシンを離れることができ、スレッドは必要ありません。他のリクエストで使用できます。
  4. リモートサービスから応答を受け取ります-続行するためにアプリプールからスレッドを取得します。
  5. リクエストが終了します。

通常、msdnを読むのは安全です。非同期パターンに関する情報はここで入手できます。

于 2012-09-06T18:57:56.020 に答える