Murat Yasar – Asp Net Application Warm Up By Using Windows Service

When you make a request for a page from any Asp.Net application, it takes server some time to respond your request. During this waiting period, some server side tasks happen.

Application Life Cycle in General According to MSDN: 1-)User requests an application resource from the Web server. 2-)ASP.NET receives the first request for the application. 3-)ASP.NET core objects are created for each request. 4-)An HttpApplication object is assigned to the request. 5-)The request is processed by the HttpApplication pipeline.

When a request is made to an application the first time, ASP.NET compiles application items. This first request’s response can be slow due to compiling process which is being done by ASP.NET. After this compilation process, the subsequent requests can get faster response than the first time response.

But if any of the following happens, this compilation process takes place again, in other words they will cause an application restart.

* When you modify the source code of your Web application. * When you add, delete or modify assemblies from the application’s Bin folder. * When you add, delete or modify localization resources from the App_GlobalResources or App_LocalResources folders. * When you add, delete or modify application’s Global.asax file. * When you add, delete or modify source code files in the App_Code directory. * When you add, delete or modify Profile configuration. * When you add, delete or modify Web service references in the App_WebReferences directory. * When you add, delete or modify the application’s Web.config file.

Take a look at the following links to get more information about this life cycle:

All pending requests will be served by the existing application domain and the old assemblies before restarting application domain, if an application restart is required.

Other than above items, an application pool can be restarted according to its own settings.

When this application restart happens, we have to wait for some time to get response from the server if we hit it the first time. Waiting can be tolerable in some cases but not all the time. The application could be very important or just annoys us to wait to get response from the application. Furthermore, do you think the visitors are patient enough to wait?

There is a good news for this situation. If you use ASP.NET 4.0 and IIS 7.5 you can set a few variable and it is done. “ASP.NET 4 ships with a new feature called “auto-start” that better addresses this scenario, and is available when ASP.NET 4 runs on IIS 7.5 (which ships with Windows 7 and Windows Server 2008 R2). The auto-start feature provides a controlled approach for starting up an application worker process, initializing an ASP.NET application, and then accepting HTTP requests.” The above line from page where Scott Guthrie talks about this specific issue.

If you serve your application from shared hosting environment and do not have much control over application pool settings, moreover you can not set isolated application pool for your application and other application causes to restart the application pool you are in and as a result you have to wait after each application pool restarting in the server. There is a solution they can offer you but what if you do not want to pay extra money for this..

While I was thinking possible solution for this, I thought if I could create a request periodically to my application, I would not get a late response. Because I might be able to warm up my application without waiting the first request to hit my app.

Afterwards I started thinking about a way of creating request automatically. I thought that a windows service might be very useful. What I did was basically I built a windows service which creates a request to URL’s. The URL addresses is read from an xml file called settings.xml.

Not very efficient but you can kind of get an information about your web application up time by inspecting logs that the service keeps. If you look at the source code you will see that a status code returns from each requests. If certain code is not returned, we take them as error and wrote its code into log.

Even though the solution seems appropriate, there is one drawback. We need a machine which will run continuously with an internet connection.

Now, I am going to try to explain each step I have taken and you should as well if you want to apply this solution. All files, executables, images used in this article are downloadable and you can see those files at the end of this writing. This settings.xml file should be at the same path where service’s executable file stays. You can write as many URL addresses as you want create request to, enable or disable logging, specify how often we should create request to URL.

All these settings can be done inside settings.xml file.

I wrote this windows service by using; —————————————————- Microsoft Visual Studio 2008 Version 9.0.30729.1 SP Microsoft .NET Framework Version 3.5 SP1 on Windows Vista Home Premium Service Pack 2

Following is the settings.xml file that the service are reading from.

1

3

You can add as many web sites as you like by adding following tags into settings.xml file.

Main part of this service is below. It simply creates a web request and takes response from the server.

//WarmUpAspNetApp section.

System.Net.HTTPWebRequest request = (System.Net.HTTPWebRequest)System.Net.WebRequest.Create(Convert.ToString(hashWhichSitesSpecification[@"WhichSites_" + i.ToString()])); request.Credentials = System.Net.CredentialCache.DefaultCredentials; request.Method = @”GET”; request.UserAgent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)”; System.Net.HTTPWebResponse response = (System.Net.HTTPWebResponse)request.GetResponse();

if (response == null

response.StatusCode != System.Net.HTTPStatusCode.OK) { writeIntoEventViewer(@”The request which was made for [" + hashWhichSitesSpecification[@"WhichSites_" + i.ToString()] + @”] returned [" + response.StatusCode.ToString() + @"] as the status code.”, System.Diagnostics.EventLogEntryType.Error); } else { if (Convert.ToInt32(hashEnableLoggingSpecification["AreWeGoingToLog"]) == 1) { writeIntoEventViewer(@”[" + hashWhichSitesSpecification[@"WhichSites_" + i.ToString()] + @”] gave response successfully.”, EventLogEntryType.Information); } }

response.Close();

//WarmUpAspNetApp section.

You can download either Visual Studio Solution File or just the necessary files to install and use this service. If you want to download solution file click on WarmUpAspNetApp.rar or just want to download the necessary files click on AspNetWarmUpService.rar from the link at the end of this writing.

Before starting install the service I assume that you have copied the necessary folder into root of C drive as follows. C:AspNetWarmUpService Following are the files which are needed to be inside this folder. C:AspNetWarmUpServiceinstallService.bat C:AspNetWarmUpServiceuninstallService.bat C:AspNetWarmUpServiceWarmUpAspNetApp.exe C:AspNetWarmUpServiceWarmUpAspNetApp.pdb C:AspNetWarmUpServiceWarmUpAspNetApp.vshost.exe C:AspNetWarmUpServiceWarmUpAspNetApp.vshost.exe.manifest C:AspNetWarmUpServicesettings.xml

Now, we can install the windows service as follows:

C:WINDOWSMicrosoft.NETFrameworkv2.0.50727InstallUtil.exe C:AspNetWarmUpServiceWarmUpAspNetApp.exe

Here I assume that you have already installed .NET framework and placed the folder named AspNetWarmUpService under C drive.

In case you need to remove this service, the following is the way to do this. Uninstalling service:

C:WINDOWSMicrosoft.NETFrameworkv2.0.50727InstallUtil.exe /u C:AspNetWarmUpServiceWarmUpAspNetApp.exe

As you can guess, this is command line where we run above lines. If you use Vista you need to open cmd.exe with Administrator privilege. If you do not, you will not be able to install or uninstall the windows service successfully. To be able to run command line with administrator privilege, you can do one of the followings:

Method A-) 1. Press the Win keyboard key or click on Vista Start button. 2. Type cmd into the Start Search textbox. 3. Press Ctrl+Shift+Enter keyboard shortcut. Ctrl-Shift-Enter is the general keyboard shortcut that triggers elevation to “Run as Administrator”. 4. Press Alt+C or press Continue to confirm the UAC elevation warning prompt.

Method B-) 1. Click on Vista Start button. 2. In the Start Search box, type in “Cmd” (without quotes). 3. Right click on the Command Prompt in the search result listing. 4. In the right click menu, click on “Run as Administrator” menu item.

After installing the windows service, we need to set up some properties of this service in order to run it properly. * Click on Vista Start button. * In the Start Search box, type in “services.msc” (without quotes). * If warning prompt appears, say continue. * Go to bottom and find WarmUpAspNet service. * Right click on it and choose properties. * Make sure startup type is set to Automatic. (It should be by default.) * Go to Recovery section and choose “Restart the Service” for first, second and subsequent failures. * Click Apply and OK. * Right click on the service and choose “Start” for starting the service.

Setting “Restart the Service” for 3 type of failures is very important. If you do not do this, service will not be able to restart itself, if something goes wrong while it is being runned. Also every 10 hours, service is being restarted in case any memory leak.

These 3 has to be set “Restart the Service” otherwise the service will not work as it is expected.

After waiting the time you specified in settings.xml file between 3 tags, you should be able to see the log inside event viewer with the key “WarmUpAspNetApp Service”. Again I assume you have enough privilege to write into event viewer. I use Windows Event Viewer to keep log on these requests. You can implement some other mechanism while you have the source code. Writing into txt file, or sending an e-mail when an error occurs or something else you appreciate with.

If you do any changing in settings.xml file, you must restart the service manually in order to take effect those changes. Otherwise, it will take effect after the service restarted by its logic.

I have explained each step I have taken here with screenshots in the following link. You can also download the solution file, only necessary files to install the service and the screenshots from this link as well.

Have a great day.