.NET Zone is brought to you in partnership with:

Maarten Balliauw is a Technical Evangelist at JetBrains. His interests are all web: ASP.NET MVC, PHP and Windows Azure. He's a Microsoft Most Valuable Professional (MVP) for Windows Azure and an ASPInsider. He has published many articles in both PHP and .NET literature such as MSDN magazine and PHP architect. Maarten is a frequent speaker at various national and international events such as MIX (Las Vegas), TechDays, DPC, ... His blog can be found at http://blog.maartenballiauw.be. Maarten is a DZone MVB and is not an employee of DZone and has posted 58 posts at DZone. You can read more from them at their website. View Full User Profile

Windows Azure and scaling: how? (.NET)

  • submit to reddit

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";
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;
11 return binding;
12 }
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);
4 var serviceConfiguration = XDocument.Parse(configurationXml);
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;
14 var changeConfigurationInput = new ChangeConfigurationInput();
15 changeConfigurationInput.Configuration = ServiceManagementHelper.EncodeToBase64String(serviceConfiguration.ToString(SaveOptions.DisableFormatting));
17 managementClient.ChangeConfigurationBySlot(subscriptionId, serviceName, slot, changeConfigurationInput);

Here’s the complete Program.cs code:

 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;
9 namespace AutoScale
10 {
11 class Program
12 {
13 private const string ServiceEndpoint = "https://management.core.windows.net";
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;
21 return binding;
22 }
24 static void Main(string[] args)
25 {
26 // Some commercial info :-)
27 Console.WriteLine("AutoScale - (c) 2011 Maarten Balliauw");
28 Console.WriteLine("");
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 }
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];
49 // Do the magic
50 var managementClient = Microsoft.Samples.WindowsAzure.ServiceManagement.ServiceManagementHelper.CreateServiceManagementChannel(
51 WebHttpBinding(), new Uri(ServiceEndpoint), new X509Certificate2(certificateFile));
53 Console.WriteLine("Retrieving current configuration...");
55 var deployment = managementClient.GetDeploymentBySlot(subscriptionId, serviceName, slot);
56 string configurationXml = ServiceManagementHelper.DecodeFromBase64String(deployment.Configuration);
58 Console.WriteLine("Updating configuration value...");
60 var serviceConfiguration = XDocument.Parse(configurationXml);
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;
70 var changeConfigurationInput = new ChangeConfigurationInput();
71 changeConfigurationInput.Configuration = ServiceManagementHelper.EncodeToBase64String(serviceConfiguration.ToString(SaveOptions.DisableFormatting));
73 Console.WriteLine("Uploading new configuration...");
75 managementClient.ChangeConfigurationBySlot(subscriptionId, serviceName, slot, changeConfigurationInput);
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)).

Published at DZone with permission of Maarten Balliauw, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)


Jaiganesh Srinivasan replied on Thu, 2011/05/26 - 7:46am

I receive a error Unhandled Exception: System.ServiceModel.ProtocolException: The remote server re turned an unexpected response: (400) Bad Request. ---> System.Net.WebException: The remote server returned an error: (400) Bad Request. at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpCha nnelAsyncRequest.CompleteGetResponse(IAsyncResult result) --- End of inner exception stack trace --- Server stack trace: at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result) at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncR esult result) at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[ ] outs, IAsyncResult result) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService(IMethodC allMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) when trying to write the content back... though reading is successful...

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.