This is another small but quite useful idea and snippet from a real Windows Azure project.
We all know that after deploying our web role to the Cloud that the first request would take a looong time. A web site’s application pool needs to be spawned, ASP.net compilation kicks in etc.
In order to already have a web site up and running and pre-warmed there are several approaches, some of them being intrinsically supported by ASP.NET – but a bit complex, IMO - and some still in beta, AFAIK. But we do not need no magic feature for this. We already have the WebRole.cs with the RoleEntryPoint-derived class. Here we do our initialization and potentially our background work.
And what could be a better candidate than periodically calling a certain (maybe the base) URL of a web site in order to keep the app pool up (if you want so!).
The following code exactly does this – based on the name of a Windows Azure internal or input endpoint (which belongs to a web site) we simply call the base address of that endpoint for the current role instance:
using System; using System.Net; using Microsoft.WindowsAzure.ServiceRuntime; namespace Thinktecture.WindowsAzure { public static class WebSiteUtilities { public static void WarmUp(string endpointName) { try { var endpoint = RoleEnvironment.CurrentRoleInstance
.InstanceEndpoints[endpointName]; var address = String.Format("{0}://{1}:{2}", endpoint.Protocol, endpoint.IPEndpoint.Address, endpoint.IPEndpoint.Port); var webClient = new WebClient(); webClient.DownloadString(address); } catch (Exception) { // intentionally swallow all exceptions here. } } } }
The actual initial and recurring warm-up call can then be placed into the Run method our our web role:
public class WebRole : RoleEntryPoint { public override void Run() { try { while (true) { Trace.WriteLine("Warming up web site..."); WebSiteUtilities.WarmUp("HttpIn"); Thread.Sleep(TimeSpan.FromMinutes(19)); } } catch (Exception ex) { DiagnosticsHelper.WriteExceptionToBlobStorage(ex); } } }
Done.
Note: I chose 19 minutes here between the calls as the default idle timeout of an IIS application pool is 20 minutes. You may want to change this to your own defaults or logic.
Hope this helps.
Nice approach, thank you for sharing. Much easier to wire-up in Azure than the IIS Application Warm-up module... bonus points for not requiring full IIS the way the module does.
Posted by: Chris Snyder | 03/04/2011 at 11:19 PM
Steve Marx posted a solution to edit the app pool timeout when the role starts:
http://blog.smarx.com/posts/controlling-application-pool-idle-timeouts-in-windows-azure
Posted by: Travis | 04/08/2011 at 07:07 PM
To make it work with HTTPS endpoints (HttpsIn), I had to change ServicePointManager.ServerCertificateValidationCallback (sorry for the formatting).
public void WarmUp(string endpointName)
{
RemoteCertificateValidationCallback allowAllCertificatesCallback = (sender, certificate, chain, sslPolicyErrors) => true;
ServicePointManager.ServerCertificateValidationCallback += allowAllCertificatesCallback;
try
{
RoleInstanceEndpoint endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[endpointName];
string address = String.Format("{0}://{1}:{2}", endpoint.Protocol, endpoint.IPEndpoint.Address, endpoint.IPEndpoint.Port);
var webClient = new WebClient();
webClient.DownloadString(address);
}
catch (Exception)
{
// intentionally swallow all exceptions here.
}
ServicePointManager.ServerCertificateValidationCallback -= allowAllCertificatesCallback;
}
Posted by: Thomento | 11/24/2011 at 05:21 PM