【问题标题】:How does ASP.NET determine whether to queue a request or not?ASP.NET 如何确定是否对请求进行排队?
【发布时间】:2011-09-01 23:35:15
【问题描述】:

当 ASP.NET 接收到一个请求时,它如何确定是服务它还是将它排队?我之所以问是因为我正在监视服务器上的性能计数器,并且 CPU 没有达到最大值,并且有大量可用的工作线程,但我仍然看到多达 200 个请求排队。

【问题讨论】:

  • 我怀疑它不会使用您的大量线程,因为这不一定有助于您的性能。对于最大性能,最好使用 1:1 的线程与 CPU 的比率。不确定 ASP .NET 内部结构
  • 线程阻塞了 I/O 操作。在这种情况下,将它们与 CPU 保持 1:1 并不能提高吞吐量。而且我认为 ASP.NET 也不会假定请求是 CPU 绑定的。我还看到并发请求达到 20 个,这比机器上的处理器数量多。
  • @RandomEnergy:这就是我说“大部分”的原因,如果他们阻塞 I/O 操作,他们就是 阻塞,这意味着他们必须等待,如果此时线程没有被切换出去,会浪费CPU。非阻塞 I/O 操作将允许其他线程在 I/O 完成时占用 CPU。

标签: asp.net threadpool


【解决方案1】:

我一直在做研究,我相信我已经找到了一个可以接受的答案。我的主要来源是这篇文章:http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx

据我了解,请求处理受到限制的主要方式有两种。第一个是 MaxConcurrentRequestsPerCPU 属性。在 .NET 4 之前,默认设置为 12。在 .NET 4 中,它更改为 5000。对于异步请求,他们希望允许很多,对于同步请求,他们认为 ASP.NET 线程池将足够好地限制同步请求。第二个当然是 ThreadPool 本身。在 ASP.NET 将请求发布到那里后,它可以决定何时发送。

如果您进行异步处理,您的限制因素可能是 CPU、网络和磁盘,而不是任何 ASP.NET 请求限制。它可能会达到 MaxConcurrentRequestsPerCPU 限制,但该限制确实很高。

如果您在很长一段时间内进行同步处理并阻止网络调用,那么您很可能会遇到这些限制。 MaxConcurrentRequestsPerCPU 在 .NET 4 之前需要注意,但仍然存在 ThreadPool。

性能测试
我做了一个简单的测试来看看这个节流是如何工作的。我有一个带有 500 毫秒 Thread.Sleep() 调用的简单页面。一台主机同时发出 800 个异步请求,一台运行 ASP.NET 的工作机处理所有这些请求。结果很有趣:

.NET 3.5,无修改:46 秒。使用进程资源管理器看到 9 个工作线程。
.NET 3.5,MaxConcurrentRequestsPerCPU 设置为 5000:46 秒。 9 个工作线程。
.NET 4:42 秒,热运行时为 13 秒。逐渐创建了大约 35 个工作线程。
.NET 4,异步:3 秒

一些观察:

  • MaxConcurrentRequestsPerCPU 未命中。看来这是线程池本身的限制。
  • .NET 3.5 似乎不太愿意让新线程来处理同步请求。 .NET 4 在处理负载方面做得更好。
  • 异步仍然是最好的。

【讨论】:

  • 这是一个有趣的结果,但您应该在服务器操作系统上运行它。显然,您在客户端操作系统(例如 Windows 7)上运行它,因为您遇到了 10 个并发请求的限制。 IIS 在服务器操作系统上没有此限制。
  • 您如何确定我“遇到了 10 个并发请求的限制”?如果是这样,为什么我的 .NET 4 测试只需要 3 秒就可以处理 800 个请求?您能否链接到任何表明在非服务器操作系统上确实存在 10 个并发请求限制的文档?
  • @Flavien,是的,请务必提供相关信息。我也遇到了似乎是 10 个并发请求的限制,并且正在寻找任何信息来支持这一点,以便我可以继续前进或找到解决方案。这是我的相关问题:stackoverflow.com/questions/29222006/…
  • 这是支持@Flavien 声明的文档:weblogs.asp.net/owscott/…
  • 有趣。我不认为我在做测试时遇到了这个限制。我观察到处理的并发请求远高于 10 个。我不记得当时我运行的是哪个操作系统。 :)
【解决方案2】:

IIS 在开始对请求进行排队之前不会使用所有可用线程,因为如果正在执行的请求需要额外的线程,这些线程需要保持可用。 IIS 被优化为优先执行请求,它不希望执行请求因为工作进程用完可用线程而被阻塞。

默认最大线程池20个,最小空闲8个,这意味着系统只会在新请求排队之前执行12个请求。最大线程数乘以核心数,但最小线程数不是,因此默认情况下,双核机器在排队之前将允许 32 个请求。

至于还有剩余的 CPU,ASP.NET 不会对其进行监控。这纯粹是关于正在使用的线程数。这些线程可能会被磁盘访问、传输数据库结果的网络访问或简单的 Thread.Sleep 阻塞,即使 CPU 未达到最大值,这些仍然会导致新请求进入队列。

有关性能的 MS 模式与实践一书中提供了更多信息。它适用于 IIS6/.NET 1.1,但概念仍然存在。 http://msdn.microsoft.com/en-us/library/ff647787.aspx#scalenetchapt06_topic8

为 IIS7 / .NET 2+ 重新配置:http://msdn.microsoft.com/en-us/library/e1f13641.aspx

【讨论】:

  • 我正在阅读关于 ThreadPool (msdn.microsoft.com/en-us/library/…) 的文档“从 .NET Framework 版本 4 开始,进程的线程池的默认大小取决于几个因素,例如虚拟地址空间。进程可以调用 GetMaxThreads 方法来确定线程数。” -- 它为我返回 400。
猜你喜欢
  • 2018-10-13
  • 2021-11-19
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
相关资源
最近更新 更多