One of the best improvements in IIS 6.0 over earlier versions was the introduction of Application Pools (often called App Pools for short). When IIS 6.0 is running in Worker Process Isolation Mode (the default in a new installation of Microsoft® Windows Server™ 2003), every IIS 6.0 site runs in an app pool. Each pool is associated with one instance of w3wp.exe, which is the host process for your applications assigned to the pool. These are referred to as “worker processes,” hence the name W3 (for www) WP (worker process) .exe.
Technically speaking, I should say “one or more instances of w3wp.exe” since you can configure a pool to have more than one worker process, but this is rarely useful. So for the sake of simplicity, and since it’s true at least 95 percent of the time, I’ll work from the assumption that each application is associated with one instance of w3wp.exe.
IIS 5.0 Process Model
With IIS 5.0, you controlled which worker process hosted the applications by marking the applications as Low, Medium (pooled), or High application protection, as shown in Figure 1.
Figure 1 IIS Web Settings
Content assigned to run in Low application protection ran in Inetinfo.exe. Inetinfo also hosted the IIS core processes. As a result, if an application failed in such a way as to halt or hang its host process, the entire Web server would stop functioning.
In Medium (pooled) application protection, applications would share an instance of dllhost.exe. This had the advantages of being isolated from Inetinfo so failing applications didn’t halt the Web server and of having multiple applications in a single process, reducing overhead for the Web server.
In High (isolated) application protection, an application (or set of applications) could be assigned to run in their own pool, isolated from both inetinfo and other dllhost instances.
While this design has worked well for many people, you cannot have as many isolated instances of dllhost.exe as would be optimal (the IIS documentation recommends a maximum of 10, but in practice you can have more). In addition, it becomes challenging to change the process identity for dllhost, which is often needed in enterprise environments, and there’s also no built-in monitoring for Web applications.
How to Allocate IIS 6.0 Application Pools
IIS 6.0 lets you configure as many application pools as you require —many thousands of pools under the right circumstances. This means that you are limited only by the resources your applications consume rather than IIS 6.0 itself. One of the decisions you have to make is how many pools you should have and what organizational structure to use. See the sidebar “Pooling Options” for some of the ways that pools are organized.
After choosing your pooling plan, remember to make useful names for your pools. When you only have a couple of pools, you don’t think much of making up a name like “Application Pool Number 2”, but if you hire someone new, are on vacation, or if the number of pools grows, an overly general name doesn’t offer much meaning as to its intended use.
Also, remember that you can use application pools as a troubleshooting technique. If you have an application which you suspect is causing problems, isolate it in its own pool. This helps you to monitor the application individually, and also ensure that it doesn’t negatively impact your other important applications.
Pool General Apps and Isolate Mission-Critical Apps In this model, mission-critical applications are in their own pool. This way you can insulate them from misbehaving applications in other pools and more easily monitor, troubleshoot, and configure the application. General-use applications can be put in a single pool to conserve resources and avoid creating more pools than necessary, which reduces administrative overhead.
Isolate Apps by Type Applications are often pooled by language or technology. While you can mix ASP.NET with classic ASP applications in the same pool, you can avoid complications by grouping applications into pools by language. For example, if both ASP and ASP.NET were in the same pool, and you had a problem with your ASP application which required that you restart the worker process, your ASP.NET applications would also be reset.
Isolate Misbehaving Apps Microsoft.com isolates misbehaving apps from well-behaving apps. New apps go into an “on probation” pool which is monitored for uptime and performance. If the app proves to be stable over time, it is moved to a pool for well-behaved apps; otherwise, it remains isolated. This has helped achieve some of the best uptime numbers on record.
Consolidate Consolidate reliable applications or static sites into a single pool. This helps group the more problem-free apps together.
Configuring App Pools
Once you’ve decided which pools to create, there’s the issue of how best to configure your pools. You can choose to accept all the default settings, and in most cases this works fine. But if you want a tune up, there are a few things you can do. For instance, I recommend that you right-click on the root App Pools node and adjust your settings there. This way all the App Pools will inherit the settings and you won’t have to configure each one individually. In addition, new pools will have the adjusted settings so they are better configured from the start.
Now let’s walk through the Application Pool properties and review some of the individual settings.
Recycling occurs when IIS 6.0 stops and restarts an application pool. This can occur due to a number of events that you can configure in the Application Pool on the Recycling tab (see Figure 2) manually or programmatically. This process, known as overlapping recycling, is designed to allow these processes to recycle gracefully. The old worker process continues to serve existing connections while new requests are routed to a new worker process. The process marked for recycling is kept in memory until it has no more requests to serve or until a configurable timeout is reached.
Figure 2 Recycling Tab
Periodic recycling of your application pools is recommended. It helps to clean up memory fragmentation, memory leaks, abandoned threads and other clutter. Keep in mind that when an application pool recycles, session state information stored in-process is lost for that pool, but other pools are not affected. ASP.NET, however, does allow you to store your session state outside the worker process, so that session information is not lost during a recycle.
Notice that Recycle worker processes (in minutes) is set to 1740 minutes (29 hours) by default. This will cause an automatic recycling to occur every day, five hours later than the previous day. You may want to consider changing this to recycle at a specific time of day when your server load is the smallest. In a Web farm, you can stagger the settings.
If you have an application that leaks memory, you can cause it to restart automatically when memory use reaches a designated threshold (see Figure 3). This is great for leaky applications—it lets you keep running without administrative intervention.
Figure 3 Performance Tab
The Idle Timeout setting is very useful on a busy server. When an application pool has not been active for 20 minutes (the default setting), the pool is shut down, freeing resources for other uses. While this is a great design for a server that has many applications and strict resource considerations, it’s not really necessary on a server that has only one or two applications and plenty of overhead.
Also, consider the case in which you have an important Web application that is used only 8 or 10 times a day, about an hour apart for each use. If the application pool was set to shut down after 20 minutes of inactivity, each person using the application would likely report that response is quite slow on the first access, but good after that. This slow response on the first request occurs when a worker process is not available to service the request. IIS must spin up a worker process and load IIS core components, the particular script engine, and sometimes compile a script before a response is returned. The client making the first request after a recycle might experience a noticeable delay in this event. In these circumstances, there is no great benefit to shutting down a worker process after 20 minutes of inactivity.
Request Queue Limit only needs adjusting in very busy server environments. If you serve several thousand requests per second and your customers receive Server Busy messages from time to time, you may want to bump up this number. But don’t raise the number unless you need to as lower numbers offer some protection against Denial of Service attacks.
Enable CPU Monitoring is not typically used. It’s better to use Performance Monitor for studying CPU use. If you really have a need for CPU throttling, Windows Service Resource Monitor is the way to go.
Web Gardens should not be set any higher than 1 for most servers. This value sets the number of worker processes used to service an application pool. Requests are sent in a round-robin fashion to the different worker process and they do not share in-process session state information. In general, the only applications that benefit from this capability are those where a resource used by the Web application is very constrained. One example is a database connection to an old back-end system that seems to bog down after four or five requests from a single connection—having more than one worker process allows you to have multiple connections, thereby improving performance. It is possible to induce problems in your application that are very difficult to diagnose by setting this to more than one worker process unnecessarily.
The defaults on the Health tab (see Figure 4) are rarely adjusted.
Figure 4 Health Tab
Enable pinging, when set, causes IIS 6.0 to automatically query a worker process to see if it is responsive. Despite the name, this is not an Internet Control Message Protocol (ICMP) ping, but rather an internal function. You will not see any network traffic as a result of this ping.
Enable rapid-fail protection is a feature that prevents an application from continuing to fail after a series of failures. There’s no point in IIS 6.0 continuously trying to start an application that is experiencing a critical problem or continues to fail repeatedly in a short period of time.
The Startup and Shutdown time limits are used to set a limit on how long IIS 6.0 will wait for an application pool to start or shut down after the worker process is told to shut down or spin up. Should it fail to follow instructions with 90 seconds, it is considered a failure for the purposes of rapid-fail protection, and the process is ended.
Again, in most cases, you will not need to adjust the process identity of the application pool (see Figure 5). The default Network Service account works to provide network access, Kerberos authentication, and is not a high privilege account. In some cases you may want to provide a unique identity, which you can do. See “Configuring Application Isolation on Windows Server 2003 and Internet Information Services (IIS) 6.0” for details on securing application pool content from other application pools.
Figure 5 Identity Tab
There are several other options you may want to configure which are not exposed in the IIS management console. The first is the LogEventOnRecycle property in the AppPools key of the IIS Metabase (located at /LM/W3SVC/AppPools). Setting this property to a value of 255 will cause all recycle events to be recorded in the event logs. They are not all recorded by default. For more information on working with the IIS Metabase, see the article entitled “Discover the IIS Metabase: Unlock the Details of Your Web Server Configuration” in the November/December 2005 issue of TechNet Magazine.
The second suggestion that I have is to add the value “ErrorLoggingFields” to the HKLMSYSTEMCurrentControlSetServicesHTTPParameters registry key with value data of 0xdff4e7. This little jewel will add the name of the Application Pool, as well as some other useful information, to any entries recorded in the httperr.log. You can find more details about error logging at Changes to HTTP API in Windows Server 2003 SP1 (165 KB Word .doc).
Wrapping It Up
Let me lay my biases on the table. I’m the IIS evangelist at Microsoft, so of course I think it’s a great server. But biases aside, the fact is that IIS 6.0 reliably serves some of the largest and most complex sites in the world. IIS 6.0 has no zero-critical security fixes since its release (as of the date of this writing), and you simply cannot do better than zero. In addition, applications running on IIS 6.0 see big improvements in uptime and performance.
Brett Hill is a Microsoft IIS Evangelist. Prior to working for Microsoft he spent three years as an IIS MVP and ran his own IIS training business. He still operates discussion groups at IISlists.com. You can reach Brett at firstname.lastname@example.org