Internet tweeps seem to be in a debate about where the coldest spot right now would be: Fargo (ND), Mars, Winnipeg (Canada) or Yakutsk (Russia) (in that order, apparently). Honestly, that’s one race I’ll gladly pass on. I hate cold, I’ll take hot over cold any day. The weather, my coffee, my wife, my Azure Web Sites, …
Wait, never heard of cold or hot Azure Web Sites?
Azure Web Sites are running in a shared pool of resources. To optimize this resource pool, the smart engineers at MS have decided that if one site in that pool does not have any user activity for roughly 20 minutes, resources are no longer allocated for that site. The IIS process for that site gets killed, and the site is now ‘cold’. After going cold, when a user connects to the site, Azure reloads your site and the site is now ‘warm’ until the next span of 20 minutes without user activity. As part of resource optimization, this 20 minute span may even be shortened if the other web sites in your web site’s resource pool are very busy (although it is believed never to go below 5 minutes).
I love Azure Web Sites and they are by far the most hassle-free way to deploy a LightSwitch application. However, I do have a couple of problems with serving up cold web sites to my customers:
- The first time a user connects after inactivity, he/she has the perceived user experience that the web site is slow, or needs to ‘wake up’. This usually happens twice a day (mornings and after lunch). If your web site is rather large (which happens quickly with LightSwitch apps), the call might even time out before Azure has your server process fully warmed up. Two timeouts per day, for LOB apps with a small amount of users especially, does not boost customer confidence.
- Even worse, if your web site happened to be a LightSwitch Desktop app (Silverlight OOB), that first call happens to be the SL app checking if the currently installed version still matches the server. If that call times out, the app displays a big red warning sign stating that the application could not check for updates and could not be started. Ouch!
- Sometimes you might want to start a background thread to do a limited amount of simple event processing (not the most reliable or scalable architecture, but by far the cheapest). When you do, you do not want to depend on user activity to keep this process from going cold.
Thankfully, if you decide there’s a good reason why your web site should not go cold, there are a number of good solutions to keep the oven burning. One is the built-in feature called ‘Always On‘ (added after this article originally was published), this article will demonstrate the same effect using Mobile Services’ Job Scheduler.
An Azure scheduled job consist out of two parts: how often do you want to run, and what do you want to run.
Schedule your job to run every 5 minutes.
I’ve done some test and these ‘5 minutes’ do not have a millisecond precision, but close enough. Besides: 5 minutes is the absolute shortest amount of time before your site goes cold if all other web sites in your pool are really busy, so we should be covered.
Then, time to paste some JavaScript in the ‘script’ tab. The only thing the script needs to do, really, is generate some ‘user activity’ in our Azure Web Site.
require('request').get({ url: "https://mysite.azurewebsites.net/HTMLClient/default.htm" });
Keeping Azure Web Sites alive means providing ‘incoming user activity’, like any HTTP GET to a web page or Web API, etc… You can use a single script to keep as many sites alive as you want. Azure should give you one free job, but it has a limitation of 16667 API calls and 165 outgoing MB per day. This means that at a pace of 1 call per site per 5 mins, you can keep 57 sites warm without spending a single penny.
In a final note, a couple of days after this writing article, an update was published adding an Azure feature called ‘Always on’. This also means ‘always billed’, and if you’re really cheap ( like me) and have more than 57 sites to keep warm (also… like me) then you could consider skipping some hours. When you do, though, don’t forget that all Azure Servers, no matter where they are deployed, always run on UTC time…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function CheckMySite() { | |
//Thanks to Sandrino Di Mattia: http://fabriccontroller.net/blog/posts/job-scheduling-in-windows-azure/ | |
warmUpSite("https://mysite.azurewebsites.net/HTMLClient/default.htm"); | |
warmUpSite("https://mysecondsite.azurewebsites.net/HTMLClient/default.htm"); | |
} | |
function warmUpSite(url) { | |
var currentdate = new Date(); | |
//Poor man's time zone conversion to Central Time | |
currentdate.setHours(currentdate.getHours() – 6); | |
//Three cheers for JS date formatting | |
var datetime = "" + (currentdate.getMonth() +1) + "/" | |
+ currentdate.getDate() + "/" | |
+ currentdate.getFullYear() + " @ " | |
+ currentdate.getHours() + ":" | |
+ currentdate.getMinutes() + ":" | |
+ currentdate.getSeconds(); | |
if( currentdate.getHours() >= 7 || currentdate.getHours() < 19) | |
{ | |
var req = require('request'); | |
req.get({ url: url }, function(error, response, body) { | |
if (!error) { | |
console.info(datetime + " Ok"); | |
} else { | |
console.error(datetime + 'error warming up ' + url + ': ' + error); | |
} | |
}); | |
} | |
else | |
{ | |
console.info("Not within office hours " + currentdate.getHours()); | |
} | |
} |
Keep rocking LS!
Jan
Pingback: Tuesday, January 7, 2014 on #WindowsAzure | Alexandre Brisebois
Pingback: Azure Website 101: Always On feature(DRAFT) | LearnWithShahriar
Pingback: Azure Website 101: Always On feature | LearnWithShahriar