This isn't a quick read, but I'm attempting to hit quite a few of the decision points I made migrating to Azure. I was skeptical, but as a result I have a nicer site architecture that is extremely scalable. I'm hoping that by laying out these areas where I had to pause and investigate I can better inform you on how to get "in the cloud".
Everyone's got their "big idea". We're gunna be like Mark Zuckerberg, but bigger, and we're going to get there faster. Well, maybe not, but, you probably have a big idea and you're concerned about the scenario that the site gets more traffic than your hardware can manage because of an outside event, the "Oprah effect". A few months ago I launched FoodBusterGame.com for the White House Apps For Healthy Kids contest. I decided to give Azure a try and also to be ready in case we won and a national press release got us that huge spike of users. For you, it might be your next big thing, your twitter or facebook.
So let's run with that, your next big thing gets mentioned on Oprah. Since you had a feeling the diva of TV might for some reason king your site you may done some / all of the following (in order of $$):
Less Scalable / Cheaper:
- Spoken with your hosting plan about if they can increase the resources to your site
- Paid for a Virtual Machine (VM) which can have it's resources expanded, to a point
- Hosted on some VM cloud service like Amazon EC2, where you could deploy more copies of a site but you haven't figured out load balancing
- Have a dedicated server hosted, and another one in a box ready to be co-located as well.
More Scalable / Expensive:
- Have an EC2 load balanced setup with multiple VMs for database, web, and maybe a CDN
- Have a load balancer, a database server and a web server, have rack space for more.
- Have a server farm, with load balancing ready to go, even while you only have 20 users.
All of these scenarios crossed my mind, and I've heard of a people implementing few other general patterns.
Furthermore, I know how to set up simple load balancing for a scalable website, I've done it at work. You basically want to assume that a client will hit the load balancer, and get Server 1 on a request, but maybe get Server 2 on the second one. Server 2 needs to have access to that user's Session data, so you have to put that session data in a shared space, like the database. Same thing with any files they upload / need to get back; there needs to be some shared storage.
However, most of us don't start out our website projects with this in mind. We do a File -> New Project and let ASP.NET store the session information in memory, and we upload user files to a folder on the hard drive of the server. That's where I started at least, and it has worked for years on small to medium web projects.
My trip to the clouds
I'll admit, last year at PDC09 I was initially a little skeptical of Azure. It seemed too "pie in the sky" (excuse the pun) to rely on, too perscribed / limiting, and too different from my normal Web Server / Database Server combo duo I've gotten used to. However, the more I use Azure, the more it has forced me to modify my project in a way that I could handle the Oprah scenario. I say "forced" because I resisted. I found that while I still had options, the more scalable, better practices began to reveal themselves. Here's how Azure made me scalable:
Step 1 - Trying to get away with the old way - everything on one Azure Web Role VM & SQL Azure
Without much fuss I was able to use the Windows Azure SDK to re-create my site in an Azure Visual Studio project. I put my project up on Azure, my tables copied to SQL Azure using SQL Migration Wizard, bada bing, I'm "in the clounds". It shouldn't be much of a surprise that you can do this because even though you don't have access to it, every Azure instance is a Windows Server VM. In fact soon Microsoft will allow remote access to these (although I'm trying to avoid needing that for simple deployment / re-deployment).
So then I thought "ok, great, I'm in the clouds". BUT, guess what happens when you want to move from 1 instance to 2? Azure adds a load balancer which does round-robin traffic directing like my datacenter example above. A user might be interacting with Server 1 on one request, then Server 2 on another. The problem occurs if I log in on one server, but on the next request I was no longer logged having hit Server 2....
Step 2 - Attempt to put my Session State in the SQL cloud
In the traditional on-site server farm scenario what I'd do is just use the ASP.NET Session State SQL provider and point my web servers to all manage session in a SQL Server database. It's pretty quick and easy. You can build the SQL tables using a single command, and you add a couple lines to your web.config on each server and you're done -- all servers share session data.
My first inclination was to try to do the exact same thing using SQL Azure. Turns out it works, but with one issue. When you do this on a physical SQL server there is a scheduled job that runs every so often to invalidate old / expired sessions. SQL Azure doesn't support timed jobs, and so you'd have to figure out a way to run the "DeleteExpiredSessions" stored procedure regularly, otherwise you'll get people logging in with stale sessions. Here's a blog that suggests you have to create a worker role (another VM type which can run a looped / repeated code): http://blogs.msdn.com/b/sqlazure/archive/2010/08/04/10046103.aspx. This seems like overkill, setting up a full VM instance just to run a command every minute or two. Maybe you could justify it if the worker role had a whole slew of other things it was doing.
My next thought was to try to game the system, keep it all in one VM and somehow run that SP (bad, ugly coding, performance degrading thoughts ensued, I was glad to see that I'm not the only one (see the comments, esp by Michael Lang: http://blogs.msdn.com/b/sqlazure/archive/2010/08/04/10046103.aspx)
Step 3 - Embrace the SessionState in Table Storage
When Azure was first launched there wasn't SQL Azure. The developers asked, and Microsoft responded with a full relational DB in the clouds. The initial thought was that we'd use table storage. That understood, a lot of the common scenarios are worked out nicely to run in TableStorage. SessionState is one of those.
I found this great blog post that helped walk me through TableStorage: http://www.intertech.com/Blog/post/Session-State-in-Windows-Azure.aspx
As the author points out, you'll need to include the AspProviders project found in the Azure Demos. This will give you the library you need: Microsoft.Samples.ServiceHosting.AspProviders.TableStorageSessionStateProvider
*Note: I'd like to echo the sentiment that this library should get added to some part of the Azure SDK, in a more permanent namespace because of how important / useful it is.
**Note: I also recommend forking over a few bucks for the Cerebrate Cloud Storage tool to view your Table / Blob storage in Azure. Big time saver.
Step 4 - Make Deploy Fun & Easy
If you use Azure in a continuos production cycle you're going to be deploying a lot. Once you deploy, it takes me about 15 minutes until the whole site is up in "staging". Do yourself a favor and set up Azure deployment in Visual Studio. If you do this right, you click "Publish" and you can walk away and get a snack while your entire site goes up for staging. Here's a great blog post on how to set this up: http://blogs.infragistics.com/blogs/anton_staykov/archive/2010/08/31/how-to-publish-your-windows-azure-application-right-from-visual-studio-2010.aspx
Behold the beauty of right-click, "Publish":
Step 5 - Blob Storage
Think of blob storage as your high-availability common file area. If a user uploads his / her profile photo, you'd put it here. The best news is that your project automatically has blog storage, and you only page for what you use. I followed this demo on setting up blob and it was pretty easy: http://msdn.microsoft.com/en-us/wazplatformtrainingcourse_exploringwindowsazurestoragevs2010_topic3.aspx
If you just want a quick-fix for saving to and reading from Azure, create a helper class and grab out of that example the following few methods:
(again, use the Cerebrate tools to view the contents)
Step 6 - Set it all up in ServiceConiguration.csfg (and ServiceDefinition.csdef)
You should just be aware that a lot of your cloud settings aren't going in Web.Config. You need to reference your TableStorage account, BlobStorage account, etc in your ServiceConfiguration.csfg (and define these points in ServiceDefinition.csdef).
If you decide to deploy to Azure you've got a lot of options. You'll find your way pretty easily, but your first trip to the clouds is going to be your most memorable. I can safely say that I'm a fan -- the Azure mimics my way of thinking, I just had to find the right tools, samples, and syntax. I love that at any moment I can scale up to 100 instances, and then back down to just 2. Oprah, over here!!!