Sunday, January 4, 2009

How I Spent My Winter Vacation : Two weeks with the Azure Services Platform

I've had the past two weeks off of work and spent the time really digging into the Azure Services Platform from Microsoft. I'll spare everyone the descriptions and assume you know how to use Google if you're unfamiliar with it. My goal, I thought, was quite simple. I would create a small web application that would serve a small number of customers (dozens, perhaps). I decided on a pet licensing application, as the data model would be fairly simple. I looked at some of the paperwork from our cat adoption, poked around a few county sites for pet licensing and came up with a simple domain model. Great! Now to build an Azure application around it!

Getting Started
The first step was to sign up for the CTP. Read my blog post about that here. It was initially a bit confusing. Mostly due to the massive number of things Microsoft unleashed on the world all at once. While waiting for my magic tokens, I prepped my machine by installing the Azure SDK, Visual Studio Tools for Azure and Azure Management Tools. Lucky for me, a good Samaritan from Microsoft was listening to my tweets and helped me get my tokens right away. It sounds like if you didn't go to the 2008 PDC, you're going to be waiting awhile for access to Azure's Hosted Services (where you run ASP.NET applications). I ended up with two storage accounts and one hosted service, plus access to SQL Data Services, Service Bus, Workflow Service and Access Control Services. Sweet!

Hello Cloud!
Like all software developers, I started off by writing "Hello World". First, I got it working on my machine using the Development Fabric, then I created a new Hosted Service and stepped my way through the prompts to deploy my application. It was relatively straight forward, but I wasn't always sure if I was doing the right thing. There are a lot of status codes like "Initializing..." and "Allocating...", but nothing to indicate how long I should twiddle my thumbs for. Speaking of thumbs, here's a rule of thumb for all things Azure: be patient. Just walk away - go get a cup of tea or harass some people in the marketing department. By the time you get back, there will probably be green lights waiting for you and you can proceed. What you have to do is usually fairly obvious, how long it will take, is not. Anyway, after some navel gazing, I had "Hello World" published to the cloud. Woohoo!

Running ASP.NET MVC on Azure
I'm a glutton for punishment. As such, I decided to cram as many new technologies into my skull as possible. I had read a few blog posts about people running ASP.NET MVC on Azure, so I thought I would give it a shot. Aaron Lerch has a fantastic piece up on how to get it up and running on the Development Fabric. Just follow the instructions! One thing to note, this ate one of my two Storage Accounts. ASP.NET MVC needs cloud-based providers for membership, role management, profiles and sessions. The samples included with the Azure SDK include everything you need and Aaron walks you through the process of setting up your application to use the appropriate providers. You should also read through the Cloudy in Seattle posts (here and here) on ASP.NET MVC and check out Maarten Balliauw's CarTrackr.

All of those posts are great and they'll definitely help you get ASP.NET MVC up and running on your local machine, but they all kind of gloss over how to deploy your application as a Hosted Service. As luck would have it, there's an excellent MSDN article that covers this very topic. By following the instructions there, I was able get ASP.NET MVC app hosted in the cloud with minimal difficulty.

Inversion of Control and Dependency Injection on Azure
One of the great things about ASP.NET MVC is that they've really been listening to the development community and respect the work the ALT.NET/xDD folks have been doing. Fundamental to xDD is the concept of inversion of control and dependency injection for the creation and management of objects. Again, I won't go into the details (your Google finger isn't broken is it?), but there are a myriad of options available: Castle Windsor, StructureMap, Unity, Ninject, Autofac... The list goes on and on. Lots of people like writing IoC containers because they're fun and functional! So my next task was to figure out which IoC container I could use with Azure and ASP.NET MVC. My needs for an IoC container were as follows: run under medium trust, cannot rely on attributes for configuration, support registration of open-ended generics and support constructor argument injection at configuration. Here's the run down:

Castle Windsor
- My preferred IoC container, but it won't run under medium trust. Out!

StructureMap
- My second favorite IoC container. Runs under medium trust locally, but not under Azure. Submitted bug report to Jeremy Miller. Reading through the StructureMap user's group, it looks like he's going to try to fix that early this year.

Ninject
- I didn't really monkey around with Ninject much. The sample code I saw was riddled with [Inject] attributes, which kinda turned me off. Apologies to @nkohari if I dismissed it too early.

Autofac
- Works great in medium trust under Azure, easy to configure, but doesn't support registering arguments for constructor injection at configuration time. You have to specify them when you resolve the service.

Unity
- No problems at all! Worked great in medium trust on Azure, easy to configure, supports everything I need! I gotta say I'm really impressed by how far Unity has come in such a short time.

Persistence, Perpetually
This is where things started to go awry. I'm an NHibernate guy. It's ridiculously easy for me to create a domain model, write up some mappings to the database and bam - persistence is done. The Entity Framework lets me do essentially the same thing, but I prefer the way NHibernate works with POCOs. I also like LINQ - a LOT. I mean seriously, I could kiss Anders Hejlsberg square on the lips. You can perhaps imagine my disappointment when I looked at the sample data access methods for Azure Table Services and SQL Data Services and saw pages and pages of infrastructure code to store even the simplest entity. Here's what I want to do:
_container.Resolve<IRepository<Contact>>().Save(new Contact { Id = Guid.NewGuid(), Name = "Fred" });
Bam! Entity in database. StorageClient (for Azure Table Services) offers something like this functionality, although you have to derive your domain objects from TableStorageEntity. Unfortunately, Azure Table Services is fairly limited at the moment - tables are non-relational and there are no joins. There's also this warning in the documentation: "The StorageClient sample library is not optimized for performance and is not intended to be used for building robust services, but only as an example of a working client library." Ouch.

At this point, SQL Data Services was starting to look a little more desirable. When I import a service reference to the SQL Data Service into a .NET project, I'm basically staring at the repository pattern. That coupled with the fact that it supports intra-container joins made me jump ship to SQL Data Services. Plus, this is about learning! I wanted to touch as much of the platform as possible. Out of the box, the only thing missing from SDS is LINQ. So after poking around for awhile and not finding anything of consequence about LINQ to SDS, I set about implementing the repository pattern and with IQueryable support. I worked on it for about two days and was probably about 80% done when I found this: SSDS REST Library. I was more than a little upset. It was buried in the noise of Google's search results and I didn't happen upon it until I was looking for some help implementing IQueryable. Sigh.

It was around this time that I thought to myself, "Self, you might be missing the forest for the trees here. What about Astoria?" Astoria is/was the code name for ADO.NET Data Services - a way of exposing access to data stores via RESTful web services. It even supports LINQ right out of the box (well, mostly)! Unfortunately, Microsoft hasn't issued a CTP for ADO.NET Data Services over SQL Data Services yet. In fact, it seems like there are some "issues" aligning the two (three, if you count Azure Table Services) offerings.

At this point, I'm a bit frustrated with the persistence picture for Azure. Yes, it's very service-oriented. There are REST APIs through the wazoo - but I don't want to spend my time building and dissecting magic strings for queries and entities. I want to type repo.Save(entity) or repo.Delete(entity) and be done with it. I will say that both Azure Table Services and SQL Data Services both seem to have nailed the data set extension problem. It's VERY easy for a multi-tenant application to extend the schema per-client. Kudos to Microsoft for that!

Ironically, the biggest problem with persistence in Azure applications is that there are so many choices. Microsoft seems to be attacking the problem from multiple directions and I'm unsure which battalion I should join up with.

Future Directions
Unfortunately, I've run out of time and I wasn't able to finish my application, but I have learned a ton about Azure and I'm fairly comfortable moving around the platform now. However, there is still so much more to learn. I didn't even scratch the surface of queues, workflow, the service bus or live ID. These are all areas I intend to investigate - but at a much slower pace. I also BARELY touched on some of the major architectural issues with building Azure applications. I had a great conversation with David Chou, Joseph Healy, Shan McArthur, Roger Jennings and others on multi-tenant Azure applications over on the Windows Azure MSDN Forums.
In the end, I'm probably going to switch to Azure Table Services and StorageClient because I can work with it offline using the Development Storage. Any future work I do with Azure will probably be done on the MAX (Portland's mass transit system), so this is more out of necessity than preference.

Overall, I gotta say I had a BLAST working with Azure! Yes, there were a few frustrating moments and plenty of rough edges, but when I look at what the blue badges are putting together, I see the future. These guys are really thinking hard about what it's going to take to build gigantic, accessible, scalable applications. This isn't just "let me host your CPU for you" - it's truly an internet-scale operating system in the making. Right now I think the two best players on the field are Microsoft and Amazon. It may seem odd that I've left Google off that list, but they don't even rate compared to what Microsoft and Amazon are offering right now. There are a handful of others out there: RightScale, Yahoo, VMWare, etc - but I think Azure is the platform to beat.


2 comments:

Jason Young said...

Thanks for the rundown of the compatible IoC containers. This was the first problem I ran into when converting an application over to Azure. I was using Spring.NET, then I tried Windsor with no luck. My attempt will be with Unity.

Nick said...

Hi,

>> Autofac - Works great in medium trust under Azure, easy to configure, but doesn’t support registering arguments for constructor injection at configuration time. You have to specify them when you resolve the service.

This is incorrect, Autofac allows constructor parameters to be specified at configuration time either through code or XML.

If you encountered any problems, can you please let me know? :)

Cheers,

Nick