Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Windows Azure, PHP, ...

About the author

Maarten Balliauw is currently employed as a Technical Evangelist at JetBrains. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Pro NuGet Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
Maarten Balliauw - MVP - Most Valuable Professional
Maarten Balliauw - ASPInsider

Search

Archive

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright Maarten Balliauw 2013


Geographically distributing Windows Azure applications using Traffic Manager

With the downtime of Amazon EC2 this week, it seems a lot of websites “in the cloud” are down at the moment. Most comments I read on Twitter (and that I also made, jokingly :-)) are in the lines of “outrageous!” and “don’t go cloud!”. While I understand these comments, I think they are wrong. These “clouds” can fail. They are even designed to fail, and often provide components and services that allow you to cope with these failures. You just have to expect failure at some point in time and build it into your application.

Let me rephrase my introduction. I just told you to expect failure, but I actually believe that clouds don’t “fail”. Yes, you may think I’m lunatic there, providing you with two different and opposing views in 2 paragraphs. Allow me to explain: "a “failing” cloud is actually a “scaling” cloud, only thing is: it’s scaling down to zero. If you design your application so that it can scale out, you should also plan for scaling “in”, eventually to zero. Use different availability zones on Amazon, and if you’re a Windows Azure user: try the new Traffic Manager CTP!

The Windows Azure Traffic Manager provides several methods of distributing internet traffic among two or more hosted services, all accessible with the same URL, in one or more Windows Azure datacenters. It’s basically a distributed DNS service that knows which Windows Azure Services are sitting behind the traffic manager URL and distributes requests based on three possible profiles:

  • Failover: all traffic is mapped to one Windows Azure service, unless it fails. It then directs all traffic to the failover Windows Azure service.
  • Performance: all traffic is mapped to the Windows Azure service “closest” (in routing terms) to the client requesting it. This will direct users from the US to one of the US datacenters, European users will probably end up in one of the European datacenters and Asian users, well, somewhere in the Asian datacenters.
  • Round-robin: Just distribute requests between various Windows Azure services defined in the Traffic Manager policy

As a sample, I have uploaded my Windows Azure package to two datacenters: EU North and US North Central. Both have their own URL:

I have created a “performance” policy at the URL http://certgen.ctp.trafficmgr.com/, which redirects users to the nearest datacenter (and fails-over if one goes down):

Windows Azure Traffic Manager geo replicate

If one of the datacenters goes down, the other service will take over. And as a bonus, I get reduced latency because users use their nearest datacenter.

So what’s this have to do with my initial thoughts? Well: design to scale, using an appropriate technique to your specific situation. Use all the tools the platform has to offer, and prepare for scaling out and for scaling '”in”, even to zero instances. And as with backups: test your disaster strategy now and then.

PS: Artwork based on Josh Twist’s sketches


Official Belgium TechDays 2011 Windows Phone 7 app released

I’m proud to announce that we (RealDolmen) have released the official Belgium TechDays 2011 Windows Phone 7 app! The official Belgium TechDays 2011 gives you the ability to browse current & upcoming sessions, as well as provide LIVE feedback to the event organizers. Is the current session awesome? Let us know! Is the food too spicy? Let us know!

Why am I blogging this? Well: one of the first sessions at the event will be Silverlight, Windows Phone 7, Windows Azure, jQuery, OData and RIA Services. Shaken, not stirred, deliverd by Kevin Dockx and myself. It will feature this WIndows Phone 7 application as well as the backoffice for it (Silverlight), the mobile web front-end (jQuery mobile), the web front-end (MVC), the integration points with the event organizers and the deployment on Windows Azure. Not to mention the twitterwall that integrates with this. ANd the top sessions ranking that will be displayed based on input from all the channels I mentioned before. In short: I’m blogging this to plug our session :-)

Interested in what we’ve built? Or just a consumer of WP7 apps? Download the app at http://techdays.realdolmen.com or directly by clicking the picture below:

Download the official Techdays 2011 application for WIndows Phone 7

See you at TechDays!


Windows Azure and scaling: how? (PHP)

One of the key ideas behind cloud computing is the concept of scaling.Talking to customers and cloud enthusiasts, many people seem to be unaware about the fact that there is great opportunity in scaling, even for small applications. In this blog post series, I will talk about the following:

Creating and uploading a management certificate

In order to keep things DRY (Don’t Repeat Yourself), I’ll just link you to the previous post (Windows Azure and scaling: how? (.NET)) for this one.

For PHP however, you’ll be needing a .pem certificate. Again, for the lazy, here’s mine (management.pfx (4.05 kb), management.cer (1.18 kb) and management.pem (5.11 kb)). If you want to create one yourself, check this site where you can convert and generate certificates.

Building a small command-line scaling tool (in PHP)

In order to be able to scale automatically, let’s build a small command-line tool in PHP. The idea is that you will be able to run the following command on a console to scale to 4 instances:

1 php autoscale.php "management.cer" "subscription-id0" "service-name" "role-name" "production" 4

Or down to 2 instances:

1 php autoscale.php "management.cer" "subscription-id" "service-name" "role-name" "production" 2

Will this work on Linux? Yup! Will this work on Windows? Yup! Now let’s get started.

The Windows Azure SDK for PHP will be quite handy to do this kind of thing. Download the latest source code (as the Microsoft_WindowsAzure_Management_Client class we’ll be using is not released officially yet).

Our script starts like this:

1 <?php 2 // Set include path 3 $path = array('./library/', get_include_path()); 4 set_include_path(implode(PATH_SEPARATOR, $path)); 5 6 // Microsoft_WindowsAzure_Management_Client 7 require_once 'Microsoft/WindowsAzure/Management/Client.php';

This is just making sure all necessary libraries have been loaded. next, call out to the Microsoft_WindowsAzure_Management_Client class’ setInstanceCountBySlot() method to set the instance count to the requested number. Easy! And in fact even easier than Microsoft's .NET version of this.

1 // Do the magic 2 $managementClient = new Microsoft_WindowsAzure_Management_Client($subscriptionId, $certificateFile, ''); 3 4 echo "Uploading new configuration...\r\n"; 5 6 $managementClient->setInstanceCountBySlot($serviceName, $slot, $roleName, $instanceCount); 7 8 echo "Finished.\r\n";

Here’s the full script:

1 <?php 2 // Set include path 3 $path = array('./library/', get_include_path()); 4 set_include_path(implode(PATH_SEPARATOR, $path)); 5 6 // Microsoft_WindowsAzure_Management_Client 7 require_once 'Microsoft/WindowsAzure/Management/Client.php'; 8 9 // Some commercial info :-) 10 echo "AutoScale - (c) 2011 Maarten Balliauw\r\n"; 11 echo "\r\n"; 12 13 // Quick-and-dirty argument check 14 if (count($argv) != 7) 15 { 16 echo "Usage:\r\n"; 17 echo " AutoScale <certificatefile> <subscriptionid> <servicename> <rolename> <slot> <instancecount>\r\n"; 18 echo "\r\n"; 19 echo "Example:\r\n"; 20 echo " AutoScale mycert.pem 39f53bb4-752f-4b2c-a873-5ed94df029e2 bing Bing.Web production 20\r\n"; 21 exit; 22 } 23 24 // Save arguments to variables 25 $certificateFile = $argv[1]; 26 $subscriptionId = $argv[2]; 27 $serviceName = $argv[3]; 28 $roleName = $argv[4]; 29 $slot = $argv[5]; 30 $instanceCount = $argv[6]; 31 32 // Do the magic 33 $managementClient = new Microsoft_WindowsAzure_Management_Client($subscriptionId, $certificateFile, ''); 34 35 echo "Uploading new configuration...\r\n"; 36 37 $managementClient->setInstanceCountBySlot($serviceName, $slot, $roleName, $instanceCount); 38 39 echo "Finished.\r\n";

Now schedule or cron this (when needed) and enjoy the benefits of scaling your Windows Azure service.

So you’re lazy? Here’s my sample project (AutoScale-PHP.zip (181.67 kb)) and the certificates used (management.pfx (4.05 kb), management.cer (1.18 kb) and management.pem (5.11 kb)).


Windows Azure and scaling: how? (.NET)

One of the key ideas behind cloud computing is the concept of scaling.Talking to customers and cloud enthusiasts, many people seem to be unaware about the fact that there is great opportunity in scaling, even for small applications. In this blog post series, I will talk about the following:

Creating and uploading a management certificate

In order to be able to programmatically (and thus possibly automated) scale your Windows Azure service, one prerequisite exists: a management certificate should be created and uploaded to Windows Azure through the management portal at http://windows.azure.com. Creating a certificate is easy: follow the instructions listed on MSDN. It’s as easy as opening a Visual Studio command prompt and issuing the following command:

1 makecert -sky exchange -r -n "CN=<CertificateName>" -pe -a sha1 -len 2048 -ss My "<CertificateName>.cer"

Too anxious to try this out? Download my certificate files (management.pfx (4.05 kb) and management.cer (1.18 kb)) and feel free to use it (password: phpazure). Beware that it’s not safe to use in production as I just shared this with the world (and you may be sharing your Windows Azure subscription with the world :-)).

Uploading the certificate through the management portal can be done under Hosted Services > Management Certificates.

Management Certificate Windows Azure

Building a small command-line scaling tool

In order to be able to scale automatically, let’s build a small command-line tool. The idea is that you will be able to run the following command on a console to scale to 4 instances:

1 AutoScale.exe "management.cer" "subscription-id0" "service-name" "role-name" "production" 4

Or down to 2 instances:.

1 AutoScale.exe "management.cer" "subscription-id0" "service-name" "role-name" "production" 2

Now let’s get started. First of all, we’ll be needing the Windows Azure service management client API SDK. Since there is no official SDK, you can download a sample at http://archive.msdn.microsoft.com/azurecmdlets. Open the solution, compile it and head for the /bin folder: we’re interested in Microsoft.Samples.WindowsAzure.ServiceManagement.dll.

Next, create a new Console Application in Visual Studio and add a reference to the above assembly. The code for Program.cs will start with the following:

1 class Program 2 { 3 private const string ServiceEndpoint = "https://management.core.windows.net"; 4 5 private static Binding WebHttpBinding() 6 { 7 var binding = new WebHttpBinding(WebHttpSecurityMode.Transport); 8 binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; 9 binding.ReaderQuotas.MaxStringContentLength = 67108864; 10 11 return binding; 12 } 13 14 static void Main(string[] args) 15 { 16 } 17 }

This constant and WebHttpBinding() method will be used by the Service Management client to connect to your Windows Azure subscription’s management API endpoint. The WebHttpBinding() creates a new WCF binding that is configured to use a certificate as the client credential. Just the way Windows Azure likes it.

I’ll skip the command-line parameter parsing. Next interesting thing is the location where a new management client is created:

1 var managementClient = Microsoft.Samples.WindowsAzure.ServiceManagement.ServiceManagementHelper.CreateServiceManagementChannel( 2 WebHttpBinding(), new Uri(ServiceEndpoint), new X509Certificate2(certificateFile));

Afterwards, the deployment details are retrieved. The deployment’s configuration is in there (base64-encoded), so the only thing to do is read that into an XDocument, update the number of instances and store it back:

1 var deployment = managementClient.GetDeploymentBySlot(subscriptionId, serviceName, slot); 2 string configurationXml = ServiceManagementHelper.DecodeFromBase64String(deployment.Configuration); 3 4 var serviceConfiguration = XDocument.Parse(configurationXml); 5 6 serviceConfiguration 7 .Descendants() 8 .Single(d => d.Name.LocalName == "Role" && d.Attributes().Single(a => a.Name.LocalName == "name").Value == roleName) 9 .Elements() 10 .Single(e => e.Name.LocalName == "Instances") 11 .Attributes() 12 .Single(a => a.Name.LocalName == "count").Value = instanceCount; 13 14 var changeConfigurationInput = new ChangeConfigurationInput(); 15 changeConfigurationInput.Configuration = ServiceManagementHelper.EncodeToBase64String(serviceConfiguration.ToString(SaveOptions.DisableFormatting)); 16 17 managementClient.ChangeConfigurationBySlot(subscriptionId, serviceName, slot, changeConfigurationInput);

Here’s the complete Program.cs code:

1 using System; 2 using System.Linq; 3 using System.Security.Cryptography.X509Certificates; 4 using System.ServiceModel; 5 using System.ServiceModel.Channels; 6 using System.Xml.Linq; 7 using Microsoft.Samples.WindowsAzure.ServiceManagement; 8 9 namespace AutoScale 10 { 11 class Program 12 { 13 private const string ServiceEndpoint = "https://management.core.windows.net"; 14 15 private static Binding WebHttpBinding() 16 { 17 var binding = new WebHttpBinding(WebHttpSecurityMode.Transport); 18 binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; 19 binding.ReaderQuotas.MaxStringContentLength = 67108864; 20 21 return binding; 22 } 23 24 static void Main(string[] args) 25 { 26 // Some commercial info :-) 27 Console.WriteLine("AutoScale - (c) 2011 Maarten Balliauw"); 28 Console.WriteLine(""); 29 30 // Quick-and-dirty argument check 31 if (args.Length != 6) 32 { 33 Console.WriteLine("Usage:"); 34 Console.WriteLine(" AutoScale.exe <certificatefile> <subscriptionid> <servicename> <rolename> <slot> <instancecount>"); 35 Console.WriteLine(""); 36 Console.WriteLine("Example:"); 37 Console.WriteLine(" AutoScale.exe mycert.cer 39f53bb4-752f-4b2c-a873-5ed94df029e2 bing Bing.Web production 20"); 38 return; 39 } 40 41 // Save arguments to variables 42 var certificateFile = args[0]; 43 var subscriptionId = args[1]; 44 var serviceName = args[2]; 45 var roleName = args[3]; 46 var slot = args[4]; 47 var instanceCount = args[5]; 48 49 // Do the magic 50 var managementClient = Microsoft.Samples.WindowsAzure.ServiceManagement.ServiceManagementHelper.CreateServiceManagementChannel( 51 WebHttpBinding(), new Uri(ServiceEndpoint), new X509Certificate2(certificateFile)); 52 53 Console.WriteLine("Retrieving current configuration..."); 54 55 var deployment = managementClient.GetDeploymentBySlot(subscriptionId, serviceName, slot); 56 string configurationXml = ServiceManagementHelper.DecodeFromBase64String(deployment.Configuration); 57 58 Console.WriteLine("Updating configuration value..."); 59 60 var serviceConfiguration = XDocument.Parse(configurationXml); 61 62 serviceConfiguration 63 .Descendants() 64 .Single(d => d.Name.LocalName == "Role" && d.Attributes().Single(a => a.Name.LocalName == "name").Value == roleName) 65 .Elements() 66 .Single(e => e.Name.LocalName == "Instances") 67 .Attributes() 68 .Single(a => a.Name.LocalName == "count").Value = instanceCount; 69 70 var changeConfigurationInput = new ChangeConfigurationInput(); 71 changeConfigurationInput.Configuration = ServiceManagementHelper.EncodeToBase64String(serviceConfiguration.ToString(SaveOptions.DisableFormatting)); 72 73 Console.WriteLine("Uploading new configuration..."); 74 75 managementClient.ChangeConfigurationBySlot(subscriptionId, serviceName, slot, changeConfigurationInput); 76 77 Console.WriteLine("Finished."); 78 } 79 } 80 }

Now schedule this (when needed) and enjoy the benefits of scaling your Windows Azure service.

So you’re lazy? Here’s my sample project (AutoScale.zip (26.31 kb)) and the certificates used (management.pfx (4.05 kb) and management.cer (1.18 kb)).

Note: I use the .cer file here because I generated it on my machine. If you are using a certificate created on another machine, a .pfx file and it's key should be used.


Windows Azure CDN updates

The Windows Azure team has just put out the new Windows Azure SDK 1.4 for download. Next to that, I noticed some interesting new capabilities for the CDN (Content Delivery Network):

  • Windows Azure CDN for Hosted Services
    Developers can use the Windows Azure Web and VM roles as “origin” for objects to be delivered at scale via the Windows Azure Content Delivery Network. Static content in your website can be automatically edge-cached at locations throughout the United States, Europe, Asia, Australia and South America to provide maximum bandwidth and lower latency delivery of website content to users.
  • Serve secure content from the Windows Azure CDN
    A new checkbox option in the Windows Azure management portal to enable delivery of secure content via HTTPS through any existing Windows Azure CDN account.

That first one looks very interesting: before today, if you wanted to use the CDN feature, you’d have to upload all static content that should be served by the CDN to your bob storage account. Today, you can just use any hosted service as your CDN “source data” provider. This means you can deploy your application on Windows Azure and have its static content (or cachable dynamic content) cached in the CDN and delivered from edge locations all over the world.

Using the Windows Azure CDN with a hosted service 

As with blob storage based CDN, the management portal will give you a domain name in the format http://<identifier>.vo.msecnd.net/. This is the CDN endpoint that will serve content you specify for caching on the CDN. Of course, a prettier domain name can be linked to this URL as well. The source for this data willl come from your hosted service's subfolder "cdn", e.g. http://maarten.cloudapp.net/cdn. This means that all content under that folder will be cached on the CDN. For example, say you have a URL http://maarten.cloudapp.net/cdn/rss.ashx. This will be cached on the CDN at http://<identifier>.vo.msecnd.net/rss.ashx. It's even possible to cache by query string, e.g. http://<identifier>.vo.msecnd.net/rss.ashx?category=Windows-Azure.

One closing hint here: make sure to specify correct cache control headers for content. This will greatly improve your end user's CDN experience and reduce bandwidth costs between your source (blob or hosted service) and the CDN in many cases.

And one closing question for the Windows Azure team: it would be great if I could use my current blog as the CDN source. It's not on Windows Azure yet I would want to use the CDN with my current host's data. This feature would also fit into the "cloud is not all or nothing" philosophy. Vote for this here :-)


Put your cloud on a diet (or: Windows Azure and scaling: why?)

Windows Azure scalingOne of the key ideas behind cloud computing is the concept of scaling.Talking to customers and cloud enthusiasts, many people seem to be unaware about the fact that there is great opportunity in scaling, even for small applications. In this blog post series, I will talk about the following:

Windows Azure and scaling: why?

Both for small and large project, scaling your application’s capacity to meet the actual demand can be valuable. Imagine a local web application that is being used mostly during office hours, with peak demand from 6 PM to 8 PM. It consists of 4 web role instances running all day, which is enough to cope with peaks. Also, the number can be increased over time to meet actual demand of the web application.

Let’s do a cost breakdown of that… In short, one small instance on Windows Azure will cost $ 0.12 per hour per instance, totaling $ 11.52 per day for this setup. If you do this estimation for a month, costs will be somewhere around $ 345.14 for the compute demand of this application, not counting storage and bandwidth.

Flashback one paragraph: peak load is during office hours and from 6 PM to 8 PM. Interesting, as this may mean the application can be running on less instances for the hours off-peak. Even more interesting: there are no office hours in the weekend (unless, uhmm, Bill Lumbergh needs you to come and work). Here’s a closer estimate of the required number of instances, per hour of day:

Windows Azure cost breakdown

Interesting! If these values are extrapolated to a month, costs will be somewhere around $ 219.31 for the compute demand of this application, not counting storage and bandwidth. That’s more than a $ 100 difference with the “always 4 instances” situation. Or over $ 1200 yearly. Imagine having a really big project and doing this: that’s a lot of beer difference :-)

Of course, this is a rough estimation, but it clearly shows there is value in scaling up and down at the right moments. The example I gave is based on a local application with clear demand differences during each day and could be scaled based on the time of day. And that’s what I will be demonstrating in the next 2 blog posts of this series: how to scale up and down automatically using the current tooling available for Windows Azure. Stay tuned!

PS: The Excel sheet I used to create the breakdown can be found here: Scaling.xlsx (11.80 kb)


Windows Azure Remote Desktop Access

The latest relase of the WIndows Azure platform, portal and tools (check here) includes support for one of the features announced at PDC last month: remote desktop access to your role instances. This feature is pretty easy to use and currently allows you to deploy a preconfigured VM with IIS where you can play with the OS. No real application needed!

Here’s how:

  1. Create a new Cloud Service and add one Web Role. This should be the result:

    image
  2. Once that is done, right click the Cloud Service and select “Publish…”
  3. In the publish dialog, click “Confiure Remote Desktop connections…”
  4. Create (or select) a certificate, make sure you also export the private key for it.
  5. Enter some credentials and set te expiration date for the account to some far future.
  6. Here’s an example of how that can look like:

    image
  7. Don’t publish yet!
  8. Navigate to http://windows.azure.com and create a new Hosted Service. In this hosted service, upload the certificate you just created:

    image
  9. Once that is done, switch back to Visual Studio, hit the Publish button and sit back while your deployment is being executed.
  10. At a given moment, you will see that deployment is ready.
  11. Switch back to your browser, click your instance and select “Connect” in the toolbar:

    image
  12. Enter your credentials, prefixed with \. E.g. “\maarten”. This is done to strip off the Windows domain from the credentials entered.
  13. RDP happyness!

    image

Scale-out to the cloud, scale back to your rack

That is a bad blog post title, really! If Steve and Ryan have this post in the Cloud Cover show news I bet they will make fun of the title. Anyway…

Imagine you have an application running in your own datacenter. Everything works smoothly, except for some capacity spikes now and then. Someone has asked you for doing something about it with low budget. Not enough budget for new hardware, and frankly new hardware would be ridiculous to just ensure capacity for a few hours each month.

A possible solution would be: migrating the application to the cloud during capacity spikes. Not all the time though: the hardware is in house and you may be a server-hugger that wants to see blinking LAN and HDD lights most of the time. I have to admit: blinking lights are cool! But I digress.

Wouldn’t it be cool to have a Powershell script that you can execute whenever a spike occurs? This script would move everything to Windows Azure. Another script should exist as well, migrating everything back once the spike cools down. Yes, you hear me coming: that’s what this blog post is about.

For those who can not wait, here’s the download: ScaleOutToTheCloud.zip (2.81 kb)

Schematical overview

Since every cool idea goes with fancy pictures, here’s a schematical overview of what could happen when you read this post to the end. First of all: you have a bunch of users making use of your application. As a good administrator, you have deployed IIS Application Request Routing as a load balancer / reverse proxy in front of your application server. Everyone is happy!

IIS Application Request Routing

Unfortunately: sometimes there are just too much users. They keep using the application and the application server catches fire.

Server catches fire!

It is time to do something. Really. Users are getting timeouts and all nasty error messages. Why not run a Powershell script that packages the entire local application for WIndows Azure and deploys the application?

Powershell to the rescue

After deployment and once the application is running in Windows Azure, there’s one thing left for that same script to do: modify ARR and re-route all traffic to Windows Azure instead of that dying server.

Request routing Azure

There you go! All users are happy again, since the application is now running in the cloud one 2, 3, or whatever number of virtual machines.

Let’s try and do this using Powershell…

The Powershell script

The Powershell script will rougly perform 5 tasks:

  • Load settings
  • Load dependencies
  • Build a list of files to deploy
  • Package these files and deploy them
  • Update IIS Application Request Routing servers

Want the download? There you go: ScaleOutToTheCloud.zip (2.81 kb)

Load settings

There are quite some parameters in play for this script. I’ve located them in a settings.ps1 file which looks like this:

# Settings (prod) $global:wwwroot = "C:\inetpub\web.local\" $global:deployProduction = 1 $global:deployDevFabric = 0 $global:webFarmIndex = 0 $global:localUrl = "web.local" $global:localPort = 80 $global:azureUrl = "scaleout-prod.cloudapp.net" $global:azurePort = 80 $global:azureDeployedSite = "http://" + $azureUrl + ":" + $azurePort $global:numberOfInstances = 1 $global:subscriptionId = "" $global:certificate = "C:\Users\Maarten\Desktop\cert.cer" $global:serviceName = "scaleout-prod" $global:storageServiceName = "" $global:slot = "Production" $global:label = Date

Let’s explain these…

$global:wwwroot The file path to the on-premise application.
$global:deployProduction Deploy to Windows Azure?
$global:deployDevFabric Deploy to development fabric?
$global:webFarmIndex The 0-based index of your webfarm. Look at IIS manager and note the order of your web farm in the list of webfarms.
$global:localUrl The on-premise URL that is registered in ARR as the application server.
$global:localPort The on-premise port that is registered in ARR as the application server.
$global:azureUrl The Windows Azure URL that will be registered in ARR as the application server.
$global:azurePort The Windows Azure port that will be registered in ARR as the application server.
$global:azureDeployedSite The final URL of the deployed Windows Azre application.
$global:numberOfInstances Number of instances to run on Windows Azure.
$global:subscriptionId Your Windows Azure subscription ID.
$global:certificate
Your certificate for managing Windows Azure.
$global:serviceName Your Windows Azure service name.
$global:storageServiceName The Windows Azure storage account that will be used for uploading the packaged application.
$global:slot The Windows Azure deployment slot (production/staging)
$global:label The label for the deployment. I chose the current date and time.

Load dependencies

Next, our script will load dependencies. There is one additional set of CmdLets tha tyou have to install: the Windows Azure management CmdLets available at http://code.msdn.microsoft.com/azurecmdlets.

Here’s the set we load:

# Load required CmdLets and assemblies $env:Path = $env:Path + "; c:\Program Files\Windows Azure SDK\v1.2\bin\" Add-PSSnapin AzureManagementToolsSnapIn [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")

Build a list of files to deploy

In order to package the application, we need a text file containing all the files that should be packaged and deployed to Windows Azure. This is done by recursively traversing the directory where the on-premise application is hosted.

 

$filesToDeploy = Get-ChildItem $wwwroot -recurse | where {$_.extension -match "\..*"} foreach ($fileToDeploy in $filesToDeploy) { $inputPath = $fileToDeploy.FullName $outputPath = $fileToDeploy.FullName.Replace($wwwroot,"") $inputPath + ";" + $outputPath | Out-File FilesToDeploy.txt -Append }

Package these files and deploy them

I have been polite and included this both for development fabric as well as Windows Azure fabric. Here’s the packaging and deployment code for development fabric:

# Package & run the website for Windows Azure (dev fabric) if ($deployDevFabric -eq 1) { trap [Exception] { del -Recurse ScaleOutService continue } cspack ServiceDefinition.csdef /roleFiles:"WebRole;FilesToDeploy.txt" /copyOnly /out:ScaleOutService /generateConfigurationFile:ServiceConfiguration.cscfg # Set instance count (Get-Content ServiceConfiguration.cscfg) | Foreach-Object {$_.Replace("count=""1""","count=""" + $numberOfInstances + """")} | Set-Content ServiceConfiguration.cscfg # Run! csrun ScaleOutService ServiceConfiguration.cscfg /launchBrowser }

And here’s the same for Windows Azure fabric:

# Package the website for Windows Azure (production) if ($deployProduction -eq 1) { cspack ServiceDefinition.csdef /roleFiles:"WebRole;FilesToDeploy.txt" /out:"ScaleOutService.cspkg" /generateConfigurationFile:ServiceConfiguration.cscfg # Set instance count (Get-Content ServiceConfiguration.cscfg) | Foreach-Object {$_.Replace("count=""1""","count=""" + $numberOfInstances + """")} | Set-Content ServiceConfiguration.cscfg # Run! (may take up to 15 minutes!) New-Deployment -SubscriptionId $subscriptionId -certificate $certificate -ServiceName $serviceName -Slot $slot -StorageServiceName $storageServiceName -Package "ScaleOutService.cspkg" -Configuration "ServiceConfiguration.cscfg" -label $label $deployment = Get-Deployment -SubscriptionId $subscriptionId -certificate $certificate -ServiceName $serviceName -Slot $slot do { Start-Sleep -s 10 $deployment = Get-Deployment -SubscriptionId $subscriptionId -certificate $certificate -ServiceName $serviceName -Slot $slot } while ($deployment.Status -ne "Suspended") Set-DeploymentStatus -Status "Running" -SubscriptionId $subscriptionId -certificate $certificate -ServiceName $serviceName -Slot $slot $wc = new-object system.net.webclient $html = "" do { Start-Sleep -s 60 trap [Exception] { continue } $html = $wc.DownloadString($azureDeployedSite) } while (!$html.ToLower().Contains("<html")) }

Update IIS Application Request Routing servers

This one can be done by abusing the .NET class Microsoft.Web.Administration.ServerManager.

# Modify IIS ARR $mgr = new-object Microsoft.Web.Administration.ServerManager $conf = $mgr.GetApplicationHostConfiguration() $section = $conf.GetSection("webFarms") $webFarms = $section.GetCollection() $webFarm = $webFarms[$webFarmIndex] $servers = $webFarm.GetCollection() $server = $servers[0] $server.SetAttributeValue("address", $azureUrl) $server.ChildElements["applicationRequestRouting"].SetAttributeValue("httpPort", $azurePort) $mgr.CommitChanges()

Running the script

Of course I’ve tested this to see if it works. And guess what: it does!

The script output itself is not very interesting. I did not add logging or meaningful messages to see what it is doing. Instead you’ll just see it working.

Powershell script running

Once it has been fired up, the Windows Azure portal will soon be showing that the application is actually deploying. No hands!

Powershell deployment to Azure

After the usual 15-20 minutes that a deployment + application first start takes, IIS ARR is re-configured by Powershell.

image

And my local users can just keep browsing to http://farm.local which now simply routes requests to Windows Azure. Don’t be fooled: I actually just packaged the default IIS website and deployed it to Windows Azure. Very performant!

image

Conclusion

It works! And it’s fancy and cool stuff. I think this may be a good deployment and scale-out model in some situations, however there may still be a bottleneck in the on-premise ARR server: if this one has too much traffic to cope with, a new burning server is in play. Note that this solution will work for any website hosted on IIS: custom made ASP.NET apps, ASP.NET MVC, PHP, …

Here’s the download: ScaleOutToTheCloud.zip (2.81 kb)


Introducing Windows Azure Companion – Cloud for the masses?

Windows Azure CompanionAt OSIDays in India, the Interoperability team at Microsoft has made an interesting series of announcements related to PHP and Windows Azure.  To summarize: Windows Azure Tools for Eclipse for PHP has been updated and is on par with Visual Studio tooling (which means you can deploy a PHP app to Windows Azure without leaving Eclipse!). The Windows Azure Command-line Tools for PHP have been updated, and there’s a new release of the Windows Azure SDK for PHP and a Windows Azure Storage plugin for WordPress built on that.

What’s most interesting in the series of announcements is the Windows Azure Companion – September 2010 Community Technology Preview(CTP). In short, compare it with Web Platform Installer but targeted at Windows Azure. It allows you to install a set of popular PHP applications on a Windows Azure instance, like WordPress or phpBB.

This list of applications seems a bit limited, but it’s not. It’s just a standard Atom feed where the Companion gets its information from. Feel free to create your own feed, or use a sample feed I created and contains following applications which I know work well on Windows Azure:

  • PHP Runtime
  • PHP Wincache Extension
  • Microsoft Drivers for PHP for SQL Server
  • Windows Azure SDK for PHP
  • PEAR Archive Tar
  • phpBB
  • Wordpress
  • eXtplorer File Manager

kick it on DotNetKicks.com

Obtaining & installing Windows Azure Companion

There are 3 steps involved in this. The first one is: go get yourself a Windows Azure subscription. I recall there is a free, limited version where you can use a virtual machine for 25 hours. Not much, but enough to try out Windows Azure Companion. Make sure to completely undeploy the application afterwards if you mind being billed.

Next, get the Windows Azure Companion – September 2010 Community Technology Preview(CTP). There is a source code download where you can compile it yourself using Visual Studio, there is also a “cspkg” version that you can just deploy onto your Windows Azure account and get running. I recommend the latter one if you want to be up and running fast.

The third step of course, is deploying. Before doing this edit the “ServiceConfiguration.cscfg” file. It needs your Windows Azure storage credentials and a administrative username/password so only you can log onto the Companion.

This configuration file also contains a reference to the application feed, so if you want to create one yourself this is the place where you can reference it.

Installing applications

Getting a “Running” state and a green bullet on the Windows Azure portal? Perfect! Then browse to http://yourchosenname.cloudapp.net:8080 (mind the port number!), this is where the administrative interface resides. Log in with the credentials you specified in “ServiceConfiguration.cscfg” before and behold the Windows Azure Companion administrative user interface.

Windows Azure Companion Administration

As a side note: this screenshot was taken with a custom feed I created which included some other applications with SQL Server support, like the Drupal 7 alpha releases. Because these are alpha’s I decided to not include them in my sample feed that you can use. I am confident that more supported applications will come in the future though.

Go to the platform tab, select the PHP runtime and other components followed by clicking “Next”. Pick your favorite version numbers and proceed with installing. After this has been finished, you can install an application from the applications tab. How about WordPress?WordPress on Windows Azure

In this last step you can choose where an application will be installed. Under the root of the website or under a virtual folder, anything you like. Afterwards, the application will be running at http://yourchosenname.cloudapp.net.

More control with eXtplorer

The sample feed I provide includes eXtplorer, a web-based file management solution. When installing this, you get full control over the applications folder on your Windows Azure instance, enabling you to edit files (configuration files) but also enabling you to upload *any* application you want to host on Windows Azure Companion. Here is me creating a highly modern homepage: and the rendered version of it:

eXtplorer on Windows AzureWelcome!

Administrative options

As with any web server, you want some administrative options. Windows Azure Companion provides you with logging of both Windows Azure and PHP. You can edit php.ini, restart the server, see memory and CPU usage statistics and create a backup of your current instance in case you want to start messing things up and want a “last known good” instance of your installation.

Windows Azure Companion AdministrationWindows Azure Companion Administration

Note: If you are a control freak, just stop your application on Windows Azure, download the virtual hard drive (.vhd) file from blob storage and make some modifications, upload it again and restart the Windows Azure Companion. I don’t recommend this as you will have to download and upload a large .vhd file but in theory it is possible to fiddle around.

Internet Explorer 9 jumplist support

A cool feature included is the IE9 jumplist support. IE9 beta is out and it seems all teams at Microsoft are adding support for it. If you drag the Windows Azure Companion administration tab to your Windows 7 taskbar, you get the following nifty shortcuts when right-clicking:

IE9 jumplist

Scalability

The current preview release of Windows Azure Companion can not provide scale-out. It can scale up to a higher number of CPU, memory and storage, but not to multiple role instances. This is due to the fact that Windows Azure drives can not be shared in read/write mode across multiple machines. On the other hand: if you deploy 2 instances and install the same apps on them, use the same SQL Azure database backend and use round-robin DNS, you can achieve scale-out at this time. Not the way you'd want it, but it should work. Then again: I don’t think that Windows Azure Companion has been created with very large sites in mind as this type of sites will benefit more from a completely optimized version for “regular” Windows Azure.

Conclusion

I’m impressed with this series of releases, especially the Windows Azure Companion. It clearly shows Microsoft is not just focusing on its own platform but also treating PHP as an equal citizen for Windows Azure. The Companion in my opinion also lowers the step to cloud computing: it’s really easy to install and use and may attract more people to the Windows Azure platform (especially if they would add a basic, entry-level subscription with low capacity and a low price, pun intended :-))

Update: also check Jim O’Neil's blog post: Windows Azure Companion: PHP and WordPress in Azure and Brian Swan's blog post: Announcing the Windows Azure Companion and More...

kick it on DotNetKicks.com


Running on Windows Azure - ChronoRace - Autoscaling

image At RealDolmen, we had the luck of doing the first (known) project on Windows Azure in Belgium. Together with Microsoft, we had the opportunity to make the ChronoRace website robust enough to withstand large sports events like the 20km through Brussels.

ChronoRace is a Belgian company based in Malmédy, specialised in electronic timing for large sports events (around 340 per year) troughout Europe in different disciplines like jogging, cycling, sailing, … Each participant is registered through the website, can consult their results and can view a high-definition video of their arrival at the finish line. Of course, these results and videos are also used to brag to co-workers and family members, resulting in about 10 result and video views per participant. Imagine 20.000 or more participants on large events… No wonder their current 1 webserver – 1 database server setup could not handle all load.

Extra investments in hardware, WAN connection upgrades and video streaming were considered, however found too expensive to have these running for 365 days a year while on average this extra capacity would only be needed for 14 days a year. Ideal for cloud computing! Especially with an expected 30.000 participants for the 20km through Brussels... (which would mean 3 TB of data transfers for the videos on 1 day!!!)

Microsoft selected RealDolmen as a partner for this project, mainly because of the knowledge we built over the past year, since the first Azure CTP. Together with ChronoRace, we gradually moved the existing SQL Server databse to SQL Azure. After that, we started moving the video streaming to blob storage, implemented extra caching and automatic scaling.

You probably have seen the following slides in various presentations on cloud computing:

Capacity cloud computing

All marketing gibberish, right? Nope! We actually managed to get very close to this model using our custom autoscaling mechanism. Here are some figures we collected during the peak of the 20km through Brussels:

Windows Azure Auto Scaling

More information on the technical challenges we encountered can be found in my slide deck I presented at KAHOSL last week:

If you want more information on scalability and automatic scaling, feel free to come to the Belgian Community Day 2010 where I will be presenting a session on this topic.

Oh and for the record: I’m not planning on writing marketing posts. I just was so impressed by our actual autoscaling graph that I had to blog this :-)