与常规CLR线程相比,为什么IIS线程如此珍贵?

And*_*ena 43 .net asp.net iis asynchronous

我正在阅读 ASP.NET MVC中的AsyncControllers.

似乎它们存在的唯一原因是,当长时间运行的工作委托给常规CLR线程时,可以保存IIS线程,这似乎更便宜.

我在这里有几个问题:

  • 为什么这些IIS线程如此昂贵,以证明为支持异步控制器而构建的整个架构?
  • 我如何知道/配置IIS应用程序池中运行的IIS线程数量?

nun*_*cal 49

ASP.NET使用.NET线程池中的线程处理请求.线程池维护一个已经引起线程初始化开销的线程池.因此,这些线程易于重用..NET线程池也是自我调整的.它监视CPU和其他资源利用率,并根据需要添加新线程或修剪线程池大小.通常应该避免手动创建线程来执行工作.而是使用线程池中的线程.同时,确保应用程序不执行可能导致线程池饥饿和拒绝HTTP请求的冗长阻塞操作非常重要.

磁盘I/O,Web服务调用都是阻塞的.最好通过使用异步调用进行优化.当您进行异步调用时,asp.net将释放您的线程,并在调用回调函数时将请求分配给另一个线程.

要配置您可以设置的线程数:

<system.web>
    <applicationPool maxConcurrentRequestsPerCPU="50" maxConcurrentThreadsPerCPU="0" requestQueueLimit="5000"/>
</system.web>
Run Code Online (Sandbox Code Playgroud)

请参阅:IIS 7.5,IIS 7.0和IIS 6.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.如果线程池中的可用线程数低于此数,则工作进程将此设置用于对来自localhost(Web应用程序将请求发送到本地Web服务的请求)的请求进行排队.此设置类似于minFreeThreads,但它仅适用于来自本地计算机的localhost请求.将minLocalRequestFreeThreads设置为76*#的CPU.

注意:本节中提供的建议不是规则.他们是一个起点.

您必须对应用程序进行基准测试,以找到最适合您应用程序的应用程序.

  • 请注意 Microsoft 最佳实践中的设置值,他的文章写于 2004 年 (!)。尽管如此,很好的答案! (2认同)
  • 调整上述数字确实有效 (2认同)

Chr*_*ris 6

IIS线程取自默认线程池,默认情况下基于处理器核心数限制.如果此线程池队列被备份,IIS将停止响应请求.通过使用异步代码,可以在执行异步操作时将线程池线程返回到池中,从而允许IIS为整体请求提供更多服务.

另一方面,自己生成一个新线程不会使用线程池线程.产生一个未经检查的独立线程数也可能是一个问题,因此它不能解决所有修复IIS线程池问题.无论哪种方式,Async IO通常都是首选.

至于更改线程池中的线程数,请在此处查看.但是,你应该真的避免这样做.


Gui*_*OND 5

我们的Web服务需要不时地为100 个请求/秒提供服务,而其余时间则为 1 个请求/秒。分析 IIS 日志,我们发现在发生突发事件时为此类调用提供服务大约需要28秒。

应用Microsoft最佳实践的@nunespascal作为引drasticly减少时间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);
Run Code Online (Sandbox Code Playgroud)

这个解决方案来自Stuart Brierley在 2009 年撰写的一篇博客文章。我们成功地在 2008 R2 到 2016 年间使用 Windows Server 对其进行了测试。