“IIS is a demand-driven web server, i.e. IIS does things only when asked for…”
This was the start of a blog post back in late 2009 announcing the beta for the IIS 7.5 Application Warm-Up module. The idea behind this module is to address a common customer need. Specifically, the demand driven nature of IIS is such that it doesn’t load application code until it’s needed to handle a request.
Many applications do a significant amount of work when they first start. And in many cases, the framework needed to run the application is loaded in the same way. Finally, it may be necessary for the application framework to compile some or all of the application code before it can handle that first request. All of this leads to an all too common situation where the unlucky client that makes the first request the application has to endure a long wait before they see the first response.
So back before IIS 7.5 was released, we asked ourselves what functionality would be needed to help to address this problem. The results of that thinking were two new features in IIS 7.5, one of them an administrative feature, and one of them a new interface in the IIS pipeline.
I’d like to talk about the pipeline change first.
The IIS pipeline is the heart of the IIS runtime – the part that determines how an IIS worker process responds to events, like the arrival of a request that needs to be served. The pipeline is a collection of event notifications and application programming interfaces (APIs) that modules can plug into and do work when things happen. The IIS product team uses these events an APIs to implement all of the interesting parts of what people think of as IIS in the form of modules. For example, IIS uses a module called StaticFileModule to be able to serve plain files. It uses a module called DefaultDocumentModule to know how to serve the default document for virtual directory or application. Modules are also used for things other than serving request. The WindowsAuthenticationModule implements Windows authentication, and the UriCacheModule implements certain caching that you don’t see, but improved the performance of the pipeline. If you are a programmer interested in the pipeline, one of the coolest decisions that we made for IIS 7.0 was to make the same interfaces that we use on the product team available to anyone. You can get started taking a look at it here.
So what does all of this have to do with warming up applications?
IIS 7.5 introduced a new event to the pipeline called GL_APPLICATION_PRELOAD. This event fires when the worker process is first starting up. A module plugged in here can register for the event to do work before the worker process notifies WAS that it is ready to handle requests. At the same time, we added a new pipeline interface that allows a module to create requests and drop them into the pipeline. These requests work just like requests from a client, except that there is no client, no network connection etc. Unless they specifically look for it, modules don’t see a difference between these “fake” requests and requests with a live client on the other end. Data that would normally be sent back to the client is discarded.
These two things together create the opportunity to solve part of the problem that I mentioned at the start of this post. When a worker process starts up, it can create a bunch of “fake” requests and send them through the pipeline. These requests will run through their respective applications without having to wait for a live client to create the demand to start.
So this looks good, but there is still a catch. IIS worker processes (which each host there own pipeline) are themselves demand started. Prior to IIS 7.5, the only way to start the worker process was for a client to make a request.
The second new IIS 7.5 feature makes it possible to automatically start an IIS worker process without waiting for a requests. This feature is pretty straightforward. To enable it, just go to the advanced properties for the application pool in Internet Information Services Manager, and set “Start Automatically” to “True”. Once you do this, worker processes for the application pool will be started up as soon as the IIS service starts. You can do the same thing by setting the startMode property in applicationhost.config to alwaysRunning.
So now, if you have a module that can send a list of requests through the pipeline, and you have the application pool set to auto start, all of the applications represented by the list of requests will be touched as soon as IIS starts.
The Application Warm-Up Module
The Application Warm-Up module that I first mentioned at the top of this post was to be the module to send the warmup requests. Why do I say this in the past tense? Back in March last year, we pulled the beta release and pointed the download page to a notice explaining that it was temporarily removed.
There were a couple of things that happened leading up to the removal. The first thing is that the functionality that I’ve listed above only solves a part of the problem. The remaining puzzle piece is that, even under the best of circumstances, there is still a period of time after starting the application where it cannot respond to client requests. If you need to restart the IIS service for any reason, even enabling Start Automatically does not help requests that arrive at the moment that the service starts. To address that, there needs to be a way for IIS to actually send a response during the warmup period. And there needs to be a way that an application can participate in what that response looks like. If we wanted to solve that problem, we needed to make a deeper investment in the module. And since we were fully engaged in the development of IIS 8, we were able to do just that as a part of the next major IIS release.
The other factor is that, when we looked at how the beta module worked, we realized that we would need to make some changes to the new pipeline functionality that we introduced in IIS7.5. Normally, when we introduce new APIs to IIS, we do so only when we are either going to use them ourselves or when we have a partner that is committed to using them before release. The pipeline changes for warmup were an exception to this because we didn’t have time to do the module before IIS 7.5 released. As sometimes happens when there is no code that depends on a new interface, we discovered that there were some things that would need to be fixed before Application Warm-Up could be made ship ready. This meant that, over and above the new functionality in the module, we would need to ship a QFE for IIS 7.5 (which is included in the setup package for Application Initialization).
Where are we now?
Finally, after almost a year after we pulled the beta, we were able to release the Release Candidate version of Application Initialization.
So that is the history up to this point for the Application Warm-Up/Initialization module. There are still questions that I’d like to answer:
- What is new in the RC?
- What’s the easiest way to start using it?
- What about advanced usage and troubleshooting?
- Why did the name change?
I am going to address these questions and more in my next few blog posts.