You may not have noticed, but this image came from the cloud!
The next stage in migrating GameMarx.com and XboxIndies.com to Azure is moving the static assets website static.gamemarx.com. This site hosts game boxart, screenshots, video thumbnails, and the podcast. In a traditional web hosting scenario, it’s common to create a static site for performance. On the server side all dynamic content and script plugins can be disabled, resulting in a faster turnaround for content. On the client side, most browsers will limit the number of concurrent connections to a single server. By using a second server for the same page, the number of concurrent connections will increase, resulting in a faster load time.
With Azure there is another good reason to add a static site – it’s cheap! Currently Azure Storage is $0.15/GB sent (uploads are free) + $0.15/GB stored per month. 20 GB of transfer per month would be a decently busy site, and would only cost $3! Running a website out of Azure Storage does not require any WebRoles or VMs, so you’re only paying for data.
When you store a file as a blob in Azure Blob Storage, the URI is created using the blob name, storage container, and storage account. The structure is:
Within the Azure control panel, you can map a custom domain name to the account. In my case I’ve setup a CNAME of static.gamemarx.com pointing to gamemarxstatic.blob.core.windows.net. The container can only include letters, numbers, and dashes. The blob name can contain pretty much anything, but special characters need to be URL escaped. My example image above has the following URI:
Where did the extra folders come from? Well, they don’t exist – like the Matrix they are just a construct of the mind. In my example, the blob is named “images/66acd000-77fe-1000-9115-d80258550998/lg_screen2.jpg”. “/” is a legal character in a blob name.
The blob name trick may be nice for the browser, but you will have to deal with reality when managing files on the server. In the Azure SDK Microsoft includes a class CloudBlobDirectory to make things easier. When you call ListBlobs() on the container, the result will (by default) will include CloudBlob and CloudBlobDirectory objects. The directory objects use the blob names to create a virtual hierarchy, and have their own ListBlobs() method plus a GetSubdirectory() method for walking the tree.
If you need to create a file in the root of the site, such as a clientaccesspolicy.xml file, you can setup a special container named “$root”. Blobs in “$root” can be accessed with or without the container name in the URL.
Be sure all the containers you create are set to public read access to avoid clients getting 403 – Forbidden errors.
Azure does not compress content automatically when requested by a client (i.e. GZip the document and send a “Content-Encoding: gzip” header). For me, this is not a big deal – I’m only serving jpegs and mp3s, which are already compressed. If however you have text documents stored, you will want to compress these not only for the Data Out savings, but to increase the page load time as well.
To enable content compression, you will need to compress the content before uploading, and set the ContentEncoding blob property to the method used. Sriram Krishnan has a good write up on sending gzip content from Azure storage. There is a downside – the content will always be served compressed, no matter the client’s AcceptEncoding headers. All modern browsers accept compressed content, but if you are supporting some non-standard clients they will not be able to read the content.
Finally, there is no default document feature in Azure Blob Storage. If you publish a fully static website to Azure Blob Storage, no one could load the homepage!
Going Web Scale!
Negatives aside, there is still another advantage for using Azure Storage beyond cost: the Azure Content Deliver Network. With a simple configuration change in the azure control panel I can send my content out to 24 datacenters around the world, speeding delivery and providing alternate routes during internet outages.
To active the CDN once you have your content in blob storage, log into the control panel and click “Create CDN”. Then point the CDN at the storage account as the “master” server, and setup a DNS CNAME and you are done.
I did not do this with my site however, because I do not have the traffic levels to warrant the need. The CDN rates are similar to Storage (nodes outside Europe and North America are $0.20/GB data out) but there is a “double charge” for content as it’s loaded into a CDN node.
When a user in London requests an image, they will first try the Europe CDN node. If the node hasn’t already cached the image, the node will request it from the Master Blob Storage Account. Then the London CDN node will send the image to the user. There will be a Data Out charge from the Master server, and again from the CDN node. Subsequent requests to the same CDN node will only have a single charge, as they will be served from cache.
Content is cached at a CDN node based upon request traffic. Since I don’t have that much traffic, it’s likely most of my content will expire before I see a real benefit. (and to be 100% honest, I cannot find anywhere that states CDN is included in the Bizspark Azure package – sorry London!).
I’d like to thank…
Once again I’d like to thank Brian H. Prince and Chris Hay for writing Azure In Action – which has a section on running a static website from blob storage.
The screenshot is from Pixel Animator 3D – an Xbox Indie Game that let’s you create animations using those Minecraft blocks (aka voxels).
10-16-2011 11:39 PM
Michael C. Neel