http://support.microsoft.com/?id=821268
从 Microsoft ASP.NET 应用程序调用 Web 服务时,您可能会遇到争用、 性能差、 和死锁。
客户端可能会报告请求停止响应 (或"挂起"),或执行很长时间。
如果怀疑死锁,则可能回收工作进程。
在应用程序事件日志中,您可能会收到以下消息。
在浏览器中,您还可能收到以下异常的错误消息:
注意:
这篇文章也适用于直接发出HttpWebRequest请求的应用程序。
- 如果您使用的 Internet Information Services (IIS) 5.0,应用程序日志中收到以下消息:
Event Type: Error Event Source: ASP.NET 1.0.3705.0 Event Category: None Event ID: 1003 Date: 5/4/2003 Time: 6:18:23 PM User: N/A Computer: <ComputerName> Description: aspnet_wp.exe (PID: <xxx>) was recycled because it was suspected to be in a deadlocked state. It did not send any responses for pending requests in the last 180 seconds.
- 如果您使用的 IIS 6.0,您可以在应用程序日志中收到以下消息:
Event Type: Warning Event Source: W3SVC-WP Event Category: None Event ID: 2262 Date: 5/4/2003 Time: 1:02:33 PM User: N/A Computer: <ComputerName> Description: ISAPI 'C:\Windows\Microsoft.net\Framework\v.1.1.4322\aspnet_isapi.dll' reported itself as unhealthy for the following reason: 'Deadlock detected'.
- 如果您使用的 IIS 6.0,则在系统日志中收到以下消息:
Event Type: Warning Event Source: W3SVC Event Category: None Event ID: 1013 Date: 5/4/2003 Time: 1:03:47 PM User: N/A Computer: <ComputerName> Description: A process serving application pool 'DefaultAppPool' exceeded time limits during shut down. The process id was '<xxxx>'.
"System.InvalidOperationException: 若要完成此操作的线程池对象中没有足够的自由线程。"
"HttpException (0x80004005): 请求超时。"
原因
因为 ASP.NET 将辅助线程和调用可用于执行请求的完成端口线程数的限制,则可能会出现此问题。
通常情况下,对 Web 服务的调用将使用一个辅助线程要执行的代码,将该请求发送和一个完成端口线程从 Web 服务接收回调。 但是,如果该请求将被重定向或要求进行身份验证,该调用可能使用最多两个辅助线程和两个完成端口线程。 因此,您可以同时发生多个 Web 服务调用时耗尽托管线程池。
例如,线程池限制为 10 个工作线程,并且所有的 10 个工作线程当前正在执行代码的等待执行的回调。 回调可以从不执行,因为排队到线程池的任何工作项被阻止,直到某个线程变得可用。
争用的另一个潜在根源是maxconnection参数的System.Net命名空间用来限制连接数。 通常情况下,这一限制就能如期作用。 但是,如果许多应用程序尝试在同一时间为单个 IP 地址使许多请求,线程可能需要等待一项可用连接。
通常情况下,对 Web 服务的调用将使用一个辅助线程要执行的代码,将该请求发送和一个完成端口线程从 Web 服务接收回调。 但是,如果该请求将被重定向或要求进行身份验证,该调用可能使用最多两个辅助线程和两个完成端口线程。 因此,您可以同时发生多个 Web 服务调用时耗尽托管线程池。
例如,线程池限制为 10 个工作线程,并且所有的 10 个工作线程当前正在执行代码的等待执行的回调。 回调可以从不执行,因为排队到线程池的任何工作项被阻止,直到某个线程变得可用。
争用的另一个潜在根源是maxconnection参数的System.Net命名空间用来限制连接数。 通常情况下,这一限制就能如期作用。 但是,如果许多应用程序尝试在同一时间为单个 IP 地址使许多请求,线程可能需要等待一项可用连接。
解决方案
要解决这些问题,您可以调整以最适合您的情况的 Machine.config 文件中以下参数:
MaxWorkerThreads参数,并使用maxIoThreads参数隐式乘以 Cpu 的数量。
例如,如果您有两个处理器,最大工作线程数是以下:
如果没有足够的线程可用,请求进行排队,直到足够的线程都可以发出请求。
因此,ASP.NET 将不会执行的以下请求数多于一次:
此设置控制的线程可以创建更快的速度比基于 CLR 的默认"线程优化"功能创建的辅助线程。
这可能会突然填充由于 slow-down 后端服务器上的 ASP.NET 请求队列的设置使 ASP.NET 对服务请求、 请求从客户端,或其它类似的突然爆发,会导致在队列中的请求数中的突然上升。
MinWorkerThreads参数的默认值为 1。
我们建议您将minWorkerThreads参数的值设置为下面的值。
默认情况下, minWorkerThreads参数不存在于 Web.config 文件或 Machine.config 文件中。
此设置将隐式地乘以 Cpu 的数量。
如果应用程序的代码而不是 IP 地址的主机名的引用的应用程序,该参数应如下所示:
最后,如果除 80 之外的端口上承载的应用程序,该参数必须与以下类似的 URI 中包含非标准的端口:
过程级别的全部内容的前面部分讨论的参数设置。但是,
maxconnection参数的设置应用到应用程序域级别。默认情况下,由于此设置将应用于应用程序域级别,您可以创建最多两个连接到特定的 IP 地址,从每个应用程序域中的您过程。
您还可以使用Server.ScriptTimeout属性来设置此限制。
注意如果您增加 executionTimeout参数的值,可能需要修改 processModelresponseDeadlockInterval参数的设置。
如果您要做如何为单个 IP 地址一个 Web 服务调用并将其保存在每个 ASPX 页面中,Microsoft 建议您使用以下配置设置:
注意当您使用此配置时,您可以执行最多 12 个ASP.NET 请求每个 CPU 同时因为 100 88 = 12。因此,至少 88 * N 工作线程和 88 * N 完成端口线程可用于其他用途 (如 Web 服务回调)。
例如,您有一台服务器有四个处理器和超线程启用。基于这些公式,可以使用下面的数值本文中提及的配置设置。
还有,当您使用此配置中,12 个连接可供每个 CPU 每个 IP 地址的每个应用程序域。因此,在下面的示例方案中,很少发生争用时请求正在等待连接和线程池不会被耗尽:
- maxWorkerThreads
- minWorkerThreads
- maxIoThreads
- minFreeThreads
- minLocalRequestFreeThreads
- maxconnection
- executionTimeout
- 限制在大约 12 种每个 CPU 的同时可以执行的 ASP.NET 请求数。
- 允许 Web 服务回调可随意使用中的线程池的线程。
- 选择适当的值为maxconnections参数。您的选择基于 IP 地址和使用的应用程序域的数量。
maxWorkerThreads和maxIoThreads
ASP.NET 使用以下两个配置设置来限制辅助线程和完成线程所使用的最大数目:
<processModel maxWorkerThreads="20" maxIoThreads="20">
2 * maxWorkerThreads
minFreeThreads和minLocalRequestFreeThreads
ASP.NET 还包含确定多少完成端口线程和辅助线程都必须可用来启动远程请求或本地请求的以下配置设置:
<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">
(
maxWorkerThreads*
Cpu 数)-
minFreeThreads
注意:
MinFreeThreads参数,并使用minLocalRequestFreeThreads参数是不隐式相乘的 Cpu 数量。
minWorkerThreads
截至 ASP.NET 1.0 Service Pack 3 和 ASP.NET 1.1 中,ASP.NET 还包含以下确定多少辅助线程可能会使其成为可立即用于远程请求提供服务的配置设置。
<processModel minWorkerThreads="1">
minWorkerThreads = maxWorkerThreads / 2
maxconnection
Maxconnection参数确定多少能连接到特定的 IP 地址。
<connectionManagement> <add address="*" maxconnection="2"> <add address="http://65.53.32.230" maxconnection="12"> </connectionManagement>
<connectionManagement> <add address="*" maxconnection="2"> <add address="http://hostname" maxconnection="12"> </connectionManagement>
<connectionManagement> <add address="*" maxconnection="2"> <add address="http://hostname:8080" maxconnection="12"> </connectionManagement>
executionTimeout
ASP.NET 使用以下配置设置来限制请求执行时间:
<httpRuntime executionTimeout="90"/>
注意如果您增加 executionTimeout参数的值,可能需要修改 processModelresponseDeadlockInterval参数的设置。
建议
建议使用本部分中的设置可能不适用于所有应用程序中。如果您要做如何为单个 IP 地址一个 Web 服务调用并将其保存在每个 ASPX 页面中,Microsoft 建议您使用以下配置设置:
- 将maxWorkerThreads参数,并使用maxIoThreads参数的值设置为100。
- 设置为maxconnection参数的值 12 *N (位置 N 为 Cpu 的数量,有)。
- 设置为minFreeThreads参数的值 88 *N 和的minLocalRequestFreeThreads参数76 *N.
- 设置50到minWorkerThreads的值。请记住,在配置文件中默认情况下不是minWorkerThreads 。您必须添加它。
注意当您使用此配置时,您可以执行最多 12 个ASP.NET 请求每个 CPU 同时因为 100 88 = 12。因此,至少 88 * N 工作线程和 88 * N 完成端口线程可用于其他用途 (如 Web 服务回调)。
例如,您有一台服务器有四个处理器和超线程启用。基于这些公式,可以使用下面的数值本文中提及的配置设置。
<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>
还有,当您使用此配置中,12 个连接可供每个 CPU 每个 IP 地址的每个应用程序域。因此,在下面的示例方案中,很少发生争用时请求正在等待连接和线程池不会被耗尽:
- Web 主机只能有一个应用程序 (应用程序域)。
- 每次请求 ASPX 页面使一个 Web 服务请求。
- 所有请求都是为同一个 IP 地址。
- 到多个 IP 地址的请求。
- 请求被重定向 (302 状态代码)。
- 请求要求身份验证。
- 请求是由多个应用程序域。