microsoft press home   All Products  |   Support  |   Search  |   microsoft.com Home  
 
  Microsoft Press Home  |   Register Books  |   Site Index  |   All Books  |

 

Advanced Search
Hot topics:
Books about:
Books for:
Products for:



Developer Featured Article
Get Ready for Windows Server 2003 and IIS 6.0
Get Ready for Windows Server 2003 and IIS 6.0 By Scott Mauvais, MCSE, MCSD, MCDBA

Over the last few months, I have been writing about what the upcoming release of Microsoft's newest operating system, Windows� Server 2003, means for us developers. In January 2003, I discussed the benefits of having the Microsoft� .NET Framework included in the operating system; in February 2003, I covered the new Application Server role. This month I will conclude this series of articles with a closer look at Microsoft Internet Information Server (IIS) 6.0.

To learn more about IIS 6.0 and Windows Server 2003, you will want to get a copy of Jerry Honeycutt's new book Introducing Microsoft Windows Server 2003. This is a great book; in addition to all the OS-level information, it has some great chapters on IIS, XML Web Services, and security, which developers will find very useful. To get a feeling for what the book covers and to make sure it is right for you, you can review the table of contents and read Chapter 15, "Deploying Windows Server 2003."

Unlike in IIS 5.0, in which some application processes often took place in the main INetInfo process, in IIS 6.0 the core Web server code has been completely separated from the application code. When a request comes in a new kernel-mode driver, http.sys picks it up. The http.sys driver sits right on top of the TCP/IP stack and simply listens for an inbound request, parses the request to determine which application it refers to (for example, http://localhost/foo/ or http://localhost/bar/), and then directly places it on a queue for a worker process to execute. Here's the important part: No user code runs in http.sys at all; it just parses and queues requests.


In earlier versions of IIS, you could run applications in the INetInfo process, so a poorly written ISAPI filter could bring down an entire Web server by crashing INetInfo. In IIS 6.0, there is no longer the concept of an in-process application-all applications are run in an isolated environment; therefore, it is impossible for an errant user app to affect the core Web server. You may be worried about the performance impact or running all applications out-of-process, but you need not be. Because http.sys places the request directly on an application's work queue, it no longer requires a separate transition to user-mode routing before handing the request off to an out-of-process application for servicing.

Now, in some cases, http.sys is able to respond to the request itself and therefore completely avoid the transition into user mode. This works only if the requested URL resolves to a static page (such as a text file or HMTL document) or to data that it has cached. The key point here is that http.sys can't execute any user code to fulfill the request. For static pages, this provides up to a 200 percent increase in performance over IIS 5.0.

Key improvements in IIS 6.0 are the new caching algorithms and the tight integration with the ASP.NET cache. As I mentioned earlier, http.sys is responsible for caching content. When a user requests a page that it has cached, http.sys fulfills the request itself rather than having to hand the request off to a worker process. Besides the improved response time for cached results, IIS 6.0 is smarter about selecting which data to cache; just because data is cachable (for example, an ASP.NET page using the @OutputCache directive) does not mean that it should be cached. The new IIS 6.0 heuristic caching algorithms examine the requested page and the Web site's access patterns to determine whether the expected performance gain from caching the item is greater than the cost of managing the item once it is in the cache. The benefits here are twofold: first IIS does not waste valuable CPU cycles caching data that is rarely used; and second, it saves the cache for data that is more likely to be reused. As a result, early testing shows that IIS 6.0 provides 165 percent more throughput than IIS 5.0 for cached response. For more information on ASP.NET's caching, see my September 2002 article, "Improve the Performance of Web Apps with New ASP.NET Caching Features."
 

IIS 6.0 Reliability

Assuming the request resolves some dynamic content, once the http.sys has queued the request, a worker process picks it up and executes the actual user code to process the request, and then generates the response back to the user. These worker processes live in application pools that completely isolate one group of applications from another. An application pool is simply one or more processes that service a given work queue. You can place multiple applications in a single application pool or you can limit your application pools to a single application. What's more, you can define the number of processes that service an application pool. So, you can have a single process service multiple applications housed in a single pool, or you can have multiple processes service a single application in a pool.

This last example, in which you have multiple processes serving a single application, is called a Web garden. Conceptually, it is the same as a Web farm. However, instead of spanning several machines, your application spans several processes. In Web gardens, http.sys distributes requests across each process similar to the way a load balancer spreads requests across different machines in a Web farm. Besides the obvious benefit of increased reliability-should one process fail, other processes in the garden will continue to respond to the load-there are a couple of more subtle reasons you should consider this approach.

First, this approach will help you work around one of the more vexing problems of server development (and Web development in particular): hot locks. Oftentimes when I review a poorly performing Web app, it turns out that there is a problem because either one tiny section of the code is poorly written or the inherent business logic has some locking issues. These issues may result from a string concatenation in a tight loop (the poorly written example) or from a long running calculation (the business requirement example). Either way, the end result is the same: when the server is under heavy load, locks in this section quickly start to back up, and then blocked threads start to cascade through the rest of the application. While implementing a Web garden does not resolve this issue, it will distribute these locks over a number of processes.

The second benefit is that deploying your apps in a Web garden from the outset forces you to deal with all the issues (such as session management and security) that you will need to address later on when you move to a Web farm. This way, you can plan for these issues in your core architecture so that you will not have to change your code (undertake an additional dev/test/release cycle) when you want to scale it out.

So far I have only discussed isolation in terms of preventing one application from crashing and taking down another application with it. You also need to account for the possibility that a poorly behaved application will tie up all the server resources and effectively deny the server to the other applications on the box. While this may not seem like a big deal to people who dedicate a Web server to a specific task or application, it is a huge deal for hosting companies.

IIS 6.0 addresses this in two ways. First, as you will see later in the Reliability section, IIS 6.0 automatically restarts applications that exceed certain thresholds such as memory usage. The second route is through the use of several quotas that IIS makes available to administrators. Using these quotas, you can limit the CPU cycles and bandwidth available to a site. If your site permits uploads, you can limit the disk space taken through the use of NTFS quotas, which limit the total space used by the identity under which the process runs, or you can limit the amount of data that can be uploaded at one time. Besides ensuring that a single application does not use up all the available disk space, this latter approach is also great for preventing malicious hackers from uploading trojans.

Should an application fail, the worst it can do is crash the worker process. While this is better than bringing down the entire server, it still leaves you in a bad spot because your application may be down. Should this happen, http.sys continues to process inbound requests and places them on the queue for processing. When the WWW service detects a failed worker process, it automatically starts up a new one to process any requests on the work queue.

So how does IIS know when a process has failed? When it starts up a new process, IIS opens a special communication channel to it. Should this process fail, it will drop this communication channel. When the channel goes dead, IIS immediately detects this and can take whatever action you specify, which is typically to restart the application. Alternatively, if it constantly fails, you can take the application pool out of service. Better yet, the response to a failed process is extensible, so you can hook your own code into the failure event. Using this approach, you could send a message to the load balancer to take the failed server out of the cluster.

This approach for dealing with failed applications works fine if the process actually crashes. However, if you have spent much time debugging ASP or ISAPI apps, you know that it is much more common for a poorly written application to hang or otherwise become non-responsive. Fortunately, IIS can address these cases also.

In addition to the communication channel, IIS performs "looks alive" testing (essentially a ping) periodically on each process. If a process fails to respond, typically IIS kills the process and starts a new one. However, you can configure it to start up a new process to handle new requests while leaving the old process running in case it was blocked performing some useful work (such as a long-running query for your boss)-thus enabling the process to complete its task. Rather than killing the task outright, you can configure IIS to attach a debugger to this orphaned process in addition to starting up a new process to handle incoming requests.

This is a huge boon to developers because it is often much easier to get to the bottom of a problem by debugging a live system than it is by diving into a dump file. The problem with debugging a live system is that it conflicts with our other need to keep systems up and running because usually no one else can access the system until we finish our debug session. The new work process model in IIS 6.0 fixes this because IIS simply spins up another process to handle the new requests and leaves the dead process in its failed state until we are finished debugging it. If you do decide to turn the setting on, be really careful because if an application fails many times, you will have many, many orphaned processes sitting around, and you will soon run out of memory.

Besides sitting around and waiting for an application to fail, IIS can proactively monitor an application and recycle after a set period of time or after certain thresholds are reached. Using this approach, you can recycle your application should the amount of physical or virtual memory grow above a preset level. This is a great approach for dealing with memory leaks in legacy code that you have inherited. Oftentimes, the cost and effort required to track down and resolve these leaks far exceeds the value of the application itself, so rather than fixing the problem it is often preferable to simply configure the hosting environment in such a way that will enable the application to limp along until you can rewrite it. You can also instruct IIS to recycle an application after a fixed number of requests or after a certain amount of elapsed time. Finally, if you detect an inconsistent state in your own code, you can also programmatically set a process to unhealthy, which will cause IIS to recycle it.
 

Increased Uptime

Beyond restarting failed and failing apps, IIS 6.0 further helps increase the uptime of your applications because its design enables you to do more maintenance without having to take your application down. For example, say you have four applications running in a single pool. Over time, the demand for one of the applications has grown significantly, and it now requires a pool of its own. In earlier versions, changing an application's isolations required taking it down. Not so in IIS 6.0; you can move an application between pools or put it in an entirely new pool while it is still running.

Because no user code runs in http.sys, you never have to take down the entire Web server to update your code. At most, an update affects a single application pool. However, unless applications in a pool share components, the pool will not be affected. On top of this level of isolation, if you developed your application with the Microsoft .NET Framework, you can update your ASP.NET pages without taking the application down. When ASP.NET detects a file has changed, it directs all new requests to the new version of the file while it drains off the current connections using the old version.

Finally, you may be worried about whether your existing application will run successfully under IIS 6.0 given all the changes I just discussed. Don't be. If your application does not support the new worker process model for some reason, you can configure IIS 6.0 to run an application under the old IIS 5.0 isolation levels. Even in this mode, applications still gain the benefits of the new kernel mode request scheduling and caching.
 

Microsoft Press Solutions

This month I started off with an architectural overview of IIS 6.0 and the new http.sys kernel-mode driver. The key architectural change is that http.sys does not execute any user code, so a poorly written application cannot crash the Web service. Next I covered changes to IIS that allow you to create and deploy much more reliable applications. Here I showed you how application pools and Web gardens increase an application's reliability by isolating it from other applications (or even other instances of itself). I also covered the new proactive features of IIS, such as application recycling, that keep applications from failing in the first place.

As I mentioned at the beginning of the article, Jerry Honeycutt's Introducing Microsoft Windows Server 2003 is the best place to learn about Windows Server 2003.

Check out the following resources for information related to developing for .NET.

For a more broad overview of all the .NET technologies, you should look at David S. Platt's Introducing Microsoft .NET. It has some great information on COM Interop, Windows Forms, and .NET memory management.

For information on developing for Windows, you will want to read Inside Microsoft Windows 2000, Third Edition, which provides the definitive guide to the internals of Windows 2000. The Microsoft product team wrote this book with full access to the source code, so you know you are getting the most comprehensive, technical information available.

Another great resource is Programming Server-Side Applications for Microsoft Windows 2000. It takes an in-depth tour of Windows 2000 services and provides expert guidance for designing and implementing applications that exploit their capabilities.

Finally, you will want to consult Active Directory� Services for Microsoft Windows 2000 Technical Reference. This practical guide to planning and deploying the Active Directory will help you design your applications to be better network citizens.

Top of Page
 
Last Updated: Wednesday, March 5, 2003