Application Initialization Module for IIS 7.5
October 5, 2012 § Leave a comment
Yesterday, One of my colleague found out best and easiest way of Application Initialization and its worth putting into my blog.
“IIS is a demand-driven web server, i.e. IIS does things only when asked for…”
you can download it from Microsoft site http://www.iis.net/downloads/microsoft/application-initialization
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?
In my last post, I gave a bit of background on the Application Warm-Up module, now called Application Initialization. This week, I would like to go into more detail as to what the Application Initialization module does, and how you should think about using it.
As I mentioned earlier, the idea behind Application Initialization is that we want to provide a way that IIS can prepare an application to serve requests without having to wait for an actual client to make a request. With Application Initialization, we break the problem down into 3 parts:
- How can I start the worker process that hosts my application without waiting for a request?
- How can I get the worker process to load my application without waiting for a request?
- How can my application send some kind of response so that clients don’t see the browser hang until the application is ready?
I would like to address the first two questions here. The third question is a bit more complex and I will save it for my next post.
Starting a worker process without waiting for a request
This is something that’s not strictly speaking a part of Application Initialization in that we added this capability as a built-in feature of IIS, starting with IIS 7.5. I will go over it here because it works hand in hand with Application Initialization to make the application available as soon as possible after starting IIS.
This feature is controlled by a the startMode property for the application pool, described (along with other application pool properties)here. The default value for startMode is OnDemand, which means that IIS will not spin up any worker processes until needed to satisfy a client request. If you set it to alwaysRunning, IIS will ensure that a worker process is always running for the application pool. This means that IIS will spin up a worker process when the World Wide Web Service is started, and it will start a new worker process if the existing one is terminated.
Note that this property should not be confused with the autoStart property. Understanding autoStart requires a bit of background knowledge. Both application pools and worker processes can be started and stopped. If an application pool is started, it means that IIS will accept requests for URLs within the pool, but it does not necessarily mean that there are any worker processes started. If an application pool is stopped, IIS will return a “503 Service Unavailable” for any requests to the application pool and it will not start any worker processes. The autoStart property is essentially a flag that IIS uses to know which application pools should be started when the World Wide Web Service is started. When you stop an application pool in IIS Manager, autoStart is set to false. When you start an application pool, autoStart is set to true. In this way, IIS ensures that the same set of application pools are running after the World Wide Web Service is started and stopped (or through a machine reboot.)
Now let’s take a quick look at the configuration for an application pool that is set to be always available. This application pool will start when the World Wide Web Service starts and it will immediately spin up a worker process.
<system.applicationHost> <applicationPools> <add name="DefaultAppPool" autoStart="true" startMode="alwaysRunning" /> </applicationPools> </system.applicationHost>
With this configuration, the Default Application Pool will immediately spin up a worker process when IIS is started, and it will spin up a new worker process when the existing one exits.
With IIS 7.5, this property was not exposed in IIS Manager. It can be set by editing the applicationhost.config file directly or by one of IIS’s scripting or programming APIs, or by the Configuration Editor UI tool. In IIS 8, we have added the startMode property to the advanced properties page for the application pools UI.
How can I get the worker process to load my application without waiting for a request?
Now that you can see how to get IIS to spin up a worker process without waiting for a request, the next thing to address is how to get an application loaded within that worker process without waiting for a request. The Application Initialization module provides a solution here, and as above, it is controlled by a single configuration property.
The Application Initialization module extends the IIS configuration by adding a new property to the application settings called preloadEnabled (in IIS 8, this property is built-in.) Let’s take a look at what this looks like in the configuration where I’ve added a new application to the default web site and enabled it for preload:
<system.applicationHost> <sites> <site name="Default Web Site" id="1"> <application path="/"> <virtualDirectory path="/" physicalPath="%SystemDrive%\inetpub\wwwroot" /> </application> <application name="AppInit" applicationPool="DefaultAppPool" preloadEnabled="true"> <virtualDirectory path="/AppInit" physicalPath="c:\inetpub\wwwroot\appinit" /> </application> </site> </sites> </system.applicationHost>
Here’s how Application Initialization uses this property. When a new worker process spins up, Application Initialization will enumerate all of the applications that it will host and checks for this property. For any application where preloadEnabled=”true”, it will build a URL corresponding to the default page for the application and run it through the pipeline. This request does not go through the network, and there is no client listening for a response (IIS discards any data that would have gone to the client.)
This “fake” request accomplishes a few key things. First, it goes through the IIS pipeline and kicks off an application start event. This initializes a number of parts inside of IIS, and if the request is for ASP.NET, it will cause global.asax to run. It also reaches the application, which will see it is the first request after starting. Typically, I expect that applications will just handle this request just like any other request from a real client, but we do set some server variables into our “fake” request, so an application with awareness of this feature could implement special processing if it chose to do so.
There is another important aspect to this process. When IIS spins up a new worker process, there is two way communication betweenWAS and the new process. This allows WAS to know precisely when the worker process is ready to accept new requests. It also allows the worker process to get information from WAS as to whether it is going to be a new process to start taking requests, or whether it’s a replacement process to take over for an older process that’s being recycled.
This is an important distinction. In the case of a new worker process, we want to start taking client requests as soon as possible, which is the way that things work outside of Application Initialization. In the case of a replacement process, though, Application Initialization will prevent the new process from reporting itself ready for new requests, until all of the preload requests (and any warumup requests, which I will discuss later) have completed. This means that no client will ever have to wait for a process recycle to complete – because the old process will continue to take requests until the new one has completed all application initialization.
In my experience, many applications with a slow startup will do their work even for a simple request to the default page. For such applications, you can take advantage of improved application recycling simply by setting preloadEnabled=”true” for that application. Similar to the startMode property above, IIS 7.5 requires you to make this setting via direct edits or applicationhost.config, or via scripting or one of our config APIs, or via the Configuration Editor UI tool. In IIS 8, we have added “Enable Preload” as a checkbox in the UI for application settings.
The two topics that I’ve covered here should get you started with Application Initialization. The ability to handle worker process recycles has been a highly requested feature.
In my next post, I’ll tackle the topic of what it means to initialize an application and what things an application developer can do to make things responsive during the time everything is warming up. This is where we’ve made major changes and added a lot of stuff since the original beta release.