Jan. 11, 2011, 8:37 a.m.
posted by roni
One of the most interesting configuration elements available is the processModel element. It is different from all the other configuration elements in several ways.
This element controls various aspects of the ASP.NET worker process (aspnet_wp.exe), including its lifetime, how many instances are created at a time, what security identity it runs under, and how large a thread pool it should use to service requests. Figure shows the attributes available with this element.
Most of the attributes shown in Figure affect the lifetime of the worker process. At first, it may seem illogical to have such precise control over how long the worker process lives. After all, why not just have it live forever, and be done with it? The sheer number of ways you can request that the worker process self-terminate and restart indicates that the ASP.NET team recognized that sometimes things go wrong—resources leak, deadlocks occur, memory limits are reached, and so on. Some of these things may be beyond your control, and the best choice in those cases is often to simply terminate the worker process and restart it. In many cases, this will have little impact on the servicing of clients because of the disconnected nature of the HTTP protocol. The primary drawbacks of a process bounce are the loss of in-process session state, application state, and entries in the data cache.
This practice of bouncing the process servicing requests is not as uncommon as you may think—many high-volume Web servers today make it a regular practice to bounce the server process periodically. The ASP.NET team recognized this in the beginning and built in a number of safeguards to ensure that the process bounce would occur smoothly and under the right conditions. This was so important in their list of goals that internally they liked to use the slogan "ASP.NET—Designed for Failure," which of course did not go over very well with the marketing people and was therefore left as an internal slogan only.
As mentioned, the conditions under which you can elect to have the server process bounce are numerous. By default, only two conditions cause the process to bounce: 1) if the total memory utilization of the process exceeds 60% of the physical memory on the machine (specified by the memoryLimit attribute) and 2) if more than 5,000 requests are queued. Both of these conditions are abnormal and should not be encountered under normal operating conditions; but if they do occur, it is likely that something is wrong and that bouncing the process may very well cure it. You can add conditions that will bounce the process, including an explicit timeout (timeout), an idle timeout (accumulated time spent idle—idleTimeout), and an upper bound on the number of requests serviced by a worker process (requestLimit).
You also have some amount of control over CPU utilization through the processModel element. For example, if your server has multiple CPUs, you can enable the webGarden attribute, to request that a dedicated worker process run on each CPU. You can also restrict which CPUs are used to host worker processes if you don't want to use them all, through the cpuMask attribute. For example, if you have a 4 CPU machine, but you want to use only processors 0, 1, and 2 to host ASP.NET worker processes, you specify webGarden as true and cpuMask as 0x00000007, which corresponds to the binary bitmask 0...0111, as shown in Listing 3-5.
<processModel enable="true" timeout="Infinite" idleTimeout="Infinite" shutdownTimeout="0:00:05" requestLimit="Infinite" requestQueueLimit="5000" restartQueueLimit="10" memoryLimit="60" webGarden="true" cpuMask="0x00000007" userName="machine" password="AutoGenerate" logLevel="Errors" clientConnectedCheck="0:00:05" comAuthenticationLevel="Connect" comImpersonationLevel="Impersonate" responseRestartDeadlockInterval="00:09:00" responseDeadlockInterval="00:03:00" maxWorkerThreads="25" maxIoThreads="25" />
Be aware that if you enable the webGarden attribute on a multi-CPU machine, session state, application state, and the global data cache are not shared between worker processes. Chapter 10 discusses ways of dealing with state sharing between processes.
The other way you have control over CPU utilization is through the number of worker and I/O threads used within the worker process to service requests. The distinction between the two types of threads is that I/O threads are bound to I/O completion ports and are used to access a particular I/O object (such as a stream or a pipe), and worker threads are traditional unrestricted threads. Currently, ASP.NET processes requests primarily on I/O threads because requests are initiated through an asynchronous write to a named pipe from IIS, the details of which we discuss in Chapter 4. These threads are drawn from the process-wide thread pool maintained for every .NET application. By default, these pools are initialized with 25 threads per CPU on the machine, which is generally a sufficient number of threads to keep the CPU utilization high. If for some reason the requests to your application end up doing a lot of waiting (for external resources, perhaps), limiting the process to 25 threads may be too constraining, in which case you could increase the number to anything less than 100. Be advised, however, that it is generally uncommon for this to be the case, and leaving the thread pools at their default of 25 should almost always be adequate.
The remaining attributes in the processModel element are related to security and are discussed further in Chapter 11.
1 Accessing Process Information
In addition to controlling various aspects of the process model, you can access information about the worker processes on a machine programmatically. The ProcessModelInfo class provides a pair of static methods to retrieve information about the current worker process and past worker processes that may have terminated recently. Each of these functions returns a reference to a ProcessInfo class populated with information about the worker process, including its age, the maximum amount of memory it has used, its process ID, how many requests it has serviced, when it was started, its status, and why it was shut down (if it was). Listing 3-6 shows the ProcessModelInfo and ProcessInfo classes. Figure shows sample output from calling ProcessModelInfo.GetHistory(10).
Public Class ProcessModelInfo Public Shared Function GetCurrentProcessInfo() _ As ProcessInfo Public Shared Function GetHistory(num As Integer) _ As ProcessInfo() End Class Public Class ProcessInfo Public ReadOnly Property Age As TimeSpan Public ReadOnly Property PeakMemoryUsed As Integer Public ReadOnly Property ProcessID As Integer Public ReadOnly Property RequestCount As Integer Public ReadOnly Property ShutdownReason _ As ProcessShutdownReason Public ReadOnly Property StartTime As DateTime Public ReadOnly Property Status As ProcessStatus End Class
2 IIS 6.0 Process Model Changes
With the release of IIS 6.0 in Windows Server 2003, the process model changes dramatically. To begin with, the processModel element in machine.config is ignored because it is replaced with equivalent settings in the IIS metabase, which is now stored in XML format in the metabase.xml file. ASP.NET is no longer hosted in aspnet_wp.exe but in one or more instances of w3wp.exe. Even more significantly, you are no longer constrained to just one worker process per CPU on a particular machine. Instead, you can configure what are called application pools, which contain collections of virtual directories that all share the same worker process. The properties of each application pool control how that particular worker process behaves, including even more settings than are available in the processModel element. Some of the new process model settings include the ability to set specific times of the day when the process should recycle; separate memory limits for virtual memory and actual used memory; CPU usage monitoring with the ability to recycle the process if utilization is too high; rapid-fail protection by disabling the application pool if it encounters a fixed number of failures within a particular time limit; and start-up and shutdown time limits.
The other significant change is that HTTP requests are now handled in kernel mode through the http.sys service. This service listens for HTTP requests and places them in the appropriate application queue. This means that inetinfo.exe is no longer the front end for HTTP requests, so the advantage of servicing requests in-process is gone. All requests are routed through the kernel-mode HTTP listener and dispatched to some process for servicing. Moving HTTP request queuing into the kernel means that faults in user-mode processes cannot adversely affect the HTTP listener, and even if a crash occurs in the user-mode request processing infrastructure, the kernel service will continue to accept and queue up requests until either the queues completely fill up or the service is shut down.
If you are moving an ASP.NET application to IIS 6.0, but you still want to use the process model and configuration settings of IIS 5.0, you can set a backward-compatibility flag in IIS 6.0 that causes it to run in IIS 5.0 isolation mode. This must be applied at the machine level, because it affects how all requests are processed on a given machine.