ASP.Net Web Application调用Web Services应注意的问题
今天看到一篇Microsoft的KB(注:Microsoft Knowledge Base Article – 821268,http://support.microsoft.com/default.aspx?scid=kb;en-us;821268 ),关于在ASP.Net Web Application调用Web Services的问题,觉得有些价值,并觉得加入blog中,与各位共享。
英文部分是Microsoft Knowledge Base Article – 821268原文,我翻译了其中部分内容。这篇KB主要是分析并解决IIS Server中出现Deaklock的问题。
SYMPTOMS-症状
When you make calls to XML Web services from an ASP.NET application, you may experience contention, poor performance, and deadlocks. Clients may report that requests stop responding (or "hang") or take a very long time to execute. If a deadlock is suspected, the worker process may be recycled. You may receive the following messages in the application event log.
当我们在ASP.Net Web Application中调用XML Web Services时,会遇到低性能和死锁(deadlock)的情况。客户端会报告请求停止响应或很长的时间才得到响应。如果检测到deaklock,服务器端的工作进程(worker process)就会回收。然后你就会在Application Event Log中看到一些异常信息。
IIS 5.0
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
ISAPI 'C:\Windows\Microsoft.net\Framework\v.1.1.4322\aspnet_isapi.dll' reported itself as unhealthy for the following reason: 'Deadlock detected'.
CAUSE-原因
This problem might occur because ASP.NET limits the number of worker threads and completion port threads that a call can use to execute requests.
问题是因为ASP.NET限制了worker threads和completion port threads的数量,这些线程在执行request的时候会用到。
Typically, a call to a Web service uses one worker thread to execute the code that sends the request and one completion port thread to receive the callback from the Web service. However, if the request is redirected or requires authentication, the call may use as many as two worker and two completion port threads. Therefore, you can exhaust the managed ThreadPool when multiple Web service calls occur at the same time.
典型的是,当web application调用Web Service时,会使用一个worker thread执行代码,发出请求。同时,也会用的一个completion port thread去接收web service的调用结果。然而,当请求被重定向或者需要认证时,就需要2个worker threads和2个completion port threads。因此,当同时调用多个Web Services时,很容易耗尽托管的线程池(ThreadPool)。
For example, suppose that the ThreadPool is limited to 10 worker threads, and all 10 worker threads are currently executing code that is waiting for a callback to execute. The callback can never execute because any work items that are queued to the ThreadPool are blocked until a thread becomes available.
例如,假定线程池限定为最多10工作线程,并且所有的10个worker threads同时运行并等待返回结果。不幸的是不可能接收到执行结果,因为所有在线程池中排队的工作项目都阻塞了直到有一个空闲的线程。
Another potential source of contention is the maxconnection parameter that the System.Net namespace uses to limit the number of connections. Generally, this limit works as expected. However, if many applications try to make many requests to a single IP address at the same time, threads may have to wait for an available connection.
另外一个潜在的问题是maxconnection参数的设置,System.Net命名空间通过这个参数来限制连接数量。一般而言,这个限制如期工作。但是,如果许多应用程序同时对一个IP发出许多请求时,线程就不得不等于一个空闲的连接。
RESOLUTION-解决措施
解决这个问题的措施是调整Machine.config文件中的一些参数。这里备份一下,如果出现上述的问题,知道怎么解决。
To resolve these problems, you can tune the following parameters in your Machine.config file to best fit your situation:
- maxWorkerThreads
- maxIoThreads
- minFreeThreads
- minLocalRequestFreeThreads
- maxconnection
- executionTimeout
To successfully resolve these problems, do the following:
- Limit the number of ASP.NET requests that can execute at the same time to approximately 12 per CPU.
- Permit Web service callbacks to freely use threads in the ThreadPool.
- Select an appropriate value for the maxconnections parameter. Base your selection on the number of IP addresses and AppDomains that are used.
Note The recommendation to limit the number of ASP.NET requests to 12 per CPU is a little arbitrary. However, this limit has proved to work well for most applications.
maxWorkerThreads and maxIoThreads
ASP.NET uses the following two configuration settings to limit the maximum number of worker threads and completion threads that are used: <processModel maxWorkerThreads="20" maxIoThreads="20">
The maxWorkerThreads parameter and the maxIoThreads parameter are implicitly multiplied by the number of CPUs. For example, if you have two processors, the maximum number of worker threads is the following:
2*maxWorkerThreads
minFreeThreads and minLocalRequestFreeThreads
ASP.NET also contains the following configuration settings that determine how many worker threads and completion port threads must be available to start a remote request or a local request:<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">
If there are not sufficient threads available, the request is queued until sufficient threads are free to make the request. Therefore, ASP.NET will not execute more than the following number of requests at the same time:
(maxWorkerThreads*number of CPUs)-minFreeThreads
Note The minFreeThreads parameter and the minLocalRequestFreeThreads parameter are not implicitly multiplied by the number of CPUs.
maxconnection
The maxconnection parameter determines how many connections can be made to a specific IP address. The parameter appears as follows:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="65.53.32.230" maxconnection="12">
</connectionManagement>
The settings for the parameters that are discussed earlier in this article are all at the process level. However, the maxconnection parameter setting applies to the AppDomain level. By default, because this setting applies to the AppDomain level, you can create a maximum of two connections to a specific IP address from each AppDomain in your process.
executionTimeout
ASP.NET uses the following configuration setting to limit the request execution time: <httpRuntime executionTimeout="90"/>
You can also set this limit by using the Server.ScriptTimeout property.
Note If you increase the value of the executionTimeout parameter, you may also have to modify the processModel responseDeadlockInterval parameter setting.
Recommendations
The settings that are recommended in this section may not work for all applications. However, the following additional information may help you to make the appropriate adjustments.
If you are making one Web service call to a single IP address from each ASPX page, Microsoft recommends that you use the following configuration settings:
- Set the values of the maxWorkerThreads parameter and the maxIoThreads parameter to 100.
- Set the value of the maxconnection parameter to 12*N (where N is the number of CPUs that you have).
- Set the values of the minFreeThreads parameter to 88*Nand the minLocalRequestFreeThreads parameter to76*N.
Note When you use this configuration, you can execute a maximum of 12 ASP.NET requests per CPU at the same time because 100-88=12. Therefore, at least 88*N worker threads and 88*N completion port threads are available for other uses (such as for the Web service callbacks).
Also, when you use this configuration, 12 connections are available per CPU per IP address for each AppDomain. Therefore, in the following scenario, very little contention occurs when requests are waiting for connections, and the ThreadPool is not exhausted:
- The Web hosts only one application (AppDomain).
- Each request for an ASPX page makes one Web service request.
- All requests are to the same IP address.
However, when you use this configuration, scenarios that involve one of the following will probably use too many connections:
- Requests are to multiple IP addresses.
- Requests are redirected (302 status code).
- Requests require authentication.
- Requests are made from multiple AppDomains.
In these scenarios, it is a good idea to use a lower value for the maxconnection parameter and higher values for the minFreeThreads parameter and the minLocalRequestFreeThreads parameter.