Archive for July, 2011

How to install IIS Application Request Routing in Windows Azure

July 21, 2011

A few months ago, I needed to use IIS Application Request Routing for my company’s main website, which runs in Windows Azure. We wanted to have some of the pages redirect to a different web application, but still show the  original domain name. We wanted to whitelist most of our current website, and let everything else redirect to the other site.

We could RDP into the instances of our web role and install ARR and put the configuration information for the reverse proxy into the web.config, and it worked great. The problem is whenever Microsoft installed a patch, or we published a new version, our changes would get wiped out. So I needed to figure out how to have this be installed and configured when the Azure instance starts up. I figured I could do this with a startup task in my web role, but what would I actually put in the script to do that?

I remembered something useful I saw at the MVP Summit (that wasn’t covered by NDA) – a cool website by Steve Marx (who’s on the Windows Azure team at Microsoft) showing cool things you can do in Azure, and one of them was installing ARR. He provides the basic commands needed. I’ll show you how to set up the whole process from soup to nuts.

Steve gives information both for running the web installation and for installing from an msi. I chose to use the msi, because I know I have tested that specific version, and I know the final version of my install scripts work with it. I was concerned about the links for the web installation changing or the version being updated and impacting my site, and I tend to be ultra-careful when it comes to things that could bring down my company’s website. I haven’t been called even once in the middle of the night since we moved to Azure, and I have found that I like sleeping through the night.

A prerequisite for the ARR software is the Web Farm Framework. So you need to download both of these msi’s. The only place I could find these downloads available was this blog. You’ll need the 64-bit versions, of course.

That article states that the URLRewrite module is also required, but it’s already included in Windows Azure, so you don’t have to worry about it.

So now you have your msi’s; when I downloaded them, they were called requestRouter_amd64_en-US.msi and webfarm_amd64_en-US.msi. Add the two MSI’s to your web role project. Right-click on the project and select “Add Existing Item”, and browse to them and select them. In the properties for each one, set the build action to ‘content’ and set ‘copy to output directory’ to ‘copy always’. If you don’t do this, they will not be included in your deployment, which makes it difficult for Azure to run them.

Now you need to write a startup task. I very cleverly called mine “InstallARR.cmd”. To create this, open Notepad or some plain text editor. Here is the first version of my startup task.

d /d "%~dp0"
msiexec /i webfarm_amd64_en-US.msi /qn /log C:\installWebfarmLog.txt
msiexec /i requestRouter_amd64_en-US.msi /qn /log C:\installARRLog.txt

%windir%\system32\inetsrv\appcmd.exe set config 
    -section:system.webServer/proxy /enabled:"True"  
    /commit:apphost >> C:\setProxyLog.txt

%windir%\system32\inetsrv\appcmd.exe set config 
    -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00 
    >> C:\setAppPool.txt

exit /b 0

This didn’t work every time. The problem is that the msiexec calls run asynchronously, and they only take a couple of seconds to run. So about half the time, the second one would fail because the first one hadn’t finished yet. Since they are running as silent installs (/qn), there wasn’t much I could do about this.

I realized I need to put a pause in after each of the installs to make sure they are done before it continues. There’s no Thread.Sleep command. So the question I have to ask you here is, “Have you ever pinged one of your Azure instances?” I have, and it doesn’t respond, but it takes 3-5 seconds to tell you that. So what could I put in the script that would stop it for 3-5 seconds before actually continuing? Yes, I did. Here’s my final script, but with my service names changed to protect the innocent.

d /d "%~dp0"
msiexec /i webfarm_amd64_en-US.msi /qn /log C:\installWebfarmLog.txt
ping innocent.goldmail.com
msiexec /i requestRouter_amd64_en-US.msi /qn /log C:\installARRLog.txt
ping notprovenguilty.goldmail.com

%windir%\system32\inetsrv\appcmd.exe set config 
    -section:system.webServer/proxy /enabled:"True"  
    /commit:apphost >> C:\setProxyLog.txt

%windir%\system32\inetsrv\appcmd.exe set config 
    -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00 
    >> C:\setAppPool.txt

exit /b 0

This worked perfectly.

Save this script as InstallARR.cmd. Add it to your project (File/AddExisting), set the build action to ‘content’ and set ‘copy to output directory’ to copy always. If you don’t do this, it won’t be included in your deployment, and Windows Azure won’t be able to run it. (Are you having a feeling of déjà vu?)

So how do you get Windows Azure to run it? You need to add it to your Service Definition file (the .csdef file in your cloud project). Just edit that file and add this right under the opening element for the <WebRole>.

<Startup>
  <Task commandLine="InstallARR.cmd" executionContext="elevated" taskType="background" />
</Startup>

Setting the executionContext to “elevated” means the task will run under the NT AUTHORITY\SYSTEM account, so you will have whatever permissions you need.

As recommended by Steve Marx, I’m running this as a background task. That way if there is a problem and it loops infinitely for some reason, I can still RDP into the machine.

I think you also need your Azure instance to be running Windows Server 2008 R2, so change the osFamily at the end of the <Service Configuration> element in the Service Configuration (cscfg) file, or add it if it’s missing.

osFamily="2" osVersion="*"

To configure the routing, add the rewrite rules to the <webserver> section of your web.config. Here’s an example. If it finds any matches in the folder or files specified in the first rule, it doesn’t redirect – it shows the page in the original website. If it doesn’t find any matches in the first rule, it checks the second rule (which in this case, handles everything not listed specifically in the first rule) and redirects to the other website.

<rewrite>
  <rules>
    <rule name="Reverse Proxy to Original Site" stopProcessing="true">
      <match url=
      "^(folder1|folder2/subfolder|awebpage.html|anasppage.aspx)(.*)" />
    </rule>
    <rule name="Reverse Proxy to Other Site" stopProcessing="true">
      <match url="(.*)" />
      <action type="Rewrite" url="http://www.otherwebsite.com/{R:1}" />
    </rule>
  </rules>
</rewrite>

Now when you publish the web application to Windows Azure, it will include the MSI’s and the startup task, run the startup task as it’s starting up the role, install and enable the IIS Application Request Routing, and use the configuration information in the web.config.

Host your ClickOnce deployment in Azure for pennies per month

July 18, 2011

A while back, I wrote an article that shows you how to host your ClickOnce deployment in Windows Azure Blob Storage. The article assumed that you already had a Windows Azure account.

Since prequels are so popular in Hollywood (Star Wars I-III, anyone?), I thought I would write a prequel to explain how much it costs to host your deployment in Azure, and how to sign up for an Azure account and create the storage account. Hopefully, this article will be more popular than Jar Jar Binks.

Show me the money

How much does it cost to host your ClickOnce deployment in Windows Azure Storage? Well, for a pay-as-you-go account, here are the costs as of today, which I found by going to here and clicking on “Pay-As-You-Go”.

Windows Azure Storage

  • $0.15 per GB stored per month
  • $0.01 per 10,000 storage transactions

    Data Transfers

    • North America and Europe regions
      • $0.15 per GB out
    • Asia Pacific Region
      • $0.20 per GB out
    • All inbound data transfers are at no charge.

Let’s take an example. Let’s say we have a deployment consisting of 150 files and a total size of 30MB. We have 100 customers, and we are going to publish a new version every month, starting in January, and all 100 customers are going to update to every version. At the end of the year, how much will this have cost us?

Put your mathlete hats on and get out your calculators. Ready? Here we go…

The storage cost for one month = $0.15 / GB * 30MB * 1GB/1000MB = $.0045. So January will be (1*value), February will be (2*value) because we’ll have two versions. March will be (3*value), and so on until December when it hits (12*value) because we have 12 versions stored. After calculating that out for the whole year, the total cost of storing the deployment files for the year will cost $0.2475. This is affordable for most people.

Let’s talk about the storage transactions. If you have a file bigger than 32MB, it is one transaction per 4MB and one at the end of the list of blocks. If the file is smaller than 32MB, it’s 1 transaction for that file. All of the files in our case are less than 32MB. So when we upload a new version of the deployment, here are the costs:

Storage Transaction cost when uploading once = 30 files * $.01/10000 = $0.00003.

Data Transfer costs are free going up, so nothing to calculate there. How about coming back down to your customer?

Transaction cost when downloading once = 30 files * $.01/10000 = $0.00003.

Data transfer cost when downloading once = 30 MB * 1GB/1000MB * $0.15/GB = $0.0045

Now you’re wishing you’d paid attention in all of those math classes, aren’t you? And we’re not done yet. Let’s calculate our total for the entire year.

  • $0.00036 = Storage Transaction cost for uploading 12 versions throughout the year.
  • $0.00 = Data Transfer cost for uploading 12 versions.
  • $0.2475 = Storage for 12 versions uploaded once per month and retained throughout the year.
  • $0.036 = Storage Transaction cost for downloading 12 versions for 100 customers.
  • $5.40 = Data Transfer cost when downloading 12 versions for 100 customers.

So our grand total is $5.68386, which is an average of 47 cents per month.

For more detailed information on Windows Azure storage costs, check out this blog entry from the Windows Azure Storage Team; it was written before they eliminated the Data Transfer cost of uploading to blob storage so don’t include that cost. Thanks to Neil McKenzie for clarification, and for providing the link to the Windows Azure Storage Team blog.

Hook me up with an Azure account

You have three basic options.

  1. If you have an MSDN subscription either through your company or because you are a bizspark customer, you probably get an MSDN benefit that more than covers your ClickOnce deployment costs. The basic mechanism for signing up will be similar, but the way you set up your storage account will be the same, so that information below should work for you as well as for those who have no MSDN account. You will have to give your credit card to cover any charges over the free usage benefit.
  2. If you want to try this out for free without giving your credit card, you can sign up for a free 30-day Azure pass. At the end of 30 days, you will have to delete the storage account and set it up on a real account if you want to continue using it. (If you use the same storage account name on the new account, the URL will be the same and your users will be able to pick up updates even though you changed accounts.)
  3. If you sign up for a pay-as-you-go account, you have to give your credit card, but you get a free benefit which would make my deployment example free for the first 3 months. Then at the end of 3 months, it will start charging your credit card, and you will not have to move your storage account. Let’s take a look at how to sign up for this type of account.

Go to http://www.microsoft.com/windowsazure/offers/ This should take you to the Windows Azure Platform Offers shown in Figure 1.


Figure 1: Windows Azure Platform Offers

Click on the Pay-As-You-Go tab and then click the Buy button on the right. Next, you will be given a choice to sign up for a new Windows Live account, or use one you already have (Figure 2).


Figure 2: Sign up or sign in.

They are going to send you e-mail on this account, so be sure it’s an account you actually check periodically. After logging in with your Windows Live account, you will be prompted for your profile information (Figure 3).


Figure 3: Profile information.

Fill in your address and phone number and click the Next button. You will be prompted for company information (Figure 4). I think you’ll find that a lot of people work for “n/a”. I doubt Microsoft looks at that information, but you can amuse yourself by putting in the name of the most popular fruit in America, just in case someone IS looking at the company names — give them a surprise. Although, it is widely reported that Apple uses Windows Azure Storage for their new iCloud service, so it might not surprise them at all. (Google would definitely surprise them!)


Figure 4: Company information

Now they will ask for your Service Usage Address. (You can check the box to use the information you filled in on the profile page.) This is displayed in Figure 5.


Figure 5: Service Usage Address.

Fill in the information and click Finish. Next you will get directions to close this page and go to the Services page. You will find yourself at the Customer Portal for the Microsoft Online Services (Figure 6).


Figure 6: Customer Portal for Microsoft Online Services

Now you get to pick a plan. If you pick the Windows Azure Platform Introductory Special, they provide some benefit for free for the first 90 days. This benefit covers our ClickOnce deployment example above, so it would be free for the first three months, and then would cost you as noted above. If you’re nuts and you don’t like free stuff and just want to pay now, You can select the Windows Azure Platform Consumption. Click the Buy Now button on your selection; you will be prompted to log in again and then taken to the Pricing and Online Subscription Agreement screen (Figure 7).


Figure 7: Pricing and Online Subscription Agreement.

Fill in your subscription name. Pick something that you like and can remember. Then read the Online Subscription agreement as carefully as you read all of these things, check the box and hit the Next button. If you don’t read it carefully, and Microsoft comes to your house to pick up your firstborn child, don’t say I didn’t warn you.

Next comes the hard part. Fill in your credit card information and click the Submit button. If your credit card information is correct, you will be sent to the Azure portal (Figure 8).

I now have an Azure account! How do I set up my new storage account?

This is the Windows Azure Portal, which you can reach through this URL: http://windows.azure.com


Figure 8: Windows Azure Portal

This screen is where you manage all of your Azure services. You can define services, set up databases, and set up storage accounts, which is what we’re here to do. Click on the ‘New Storage Account’ icon at the top of the screen as shown in Figure 9.


Figure 9:Create a new storage account

Next you will be prompted for your new storage account name (Figure 10). This will be used in the URLs for accessing your deployment, so you should probably think twice before making it something like “myapplicationsux” or “mypornpix”. The name must have only lowercase letters and numbers. After you fill it in, it will tell you if it’s already used. If it doesn’t give you any errors, it’s available.

In regards to the region, you will be asked to either choose a region, choose an affinity group, or create a new affinity group. This is not something you can change later, so choose wisely. (Unlike Walter Donovan in Indiana Jones and the Last Crusade, if you choose poorly, you will not instantly grow ancient and disintegrate.)


Figure 10: Create a new storage account

An affinity group is basically specifying a location and naming it. You can then choose the affinity group when setting up other services to ensure that your compute instances and your data are in the same region, which will make them as performant as possible.

Just in case you ever want to use this account  for something other than Blob Storage, I recommend setting up an affinity group. Select the radio button for “Create or choose an affinity group”, and then select the dropdown. Then you can select the location – be sure to use the dropdown. Mine defaulted to “anywhere in the US”, but it’s better to select a specific region, such as North Central or South Central, or whatever region is closest to you. Then click OK to go ahead and create the storage account. You should now see your storage account in the Windows Azure Portal (Figure 11).


Figure 11: Storage Account

You can assign a custom DNS entry to your storage account by clicking the Add Domain button on the top of the screen and following the instructions.

The URL for accessing your blob storage is on the right side of the screen. Mine is robindotnet.blob.core.windows.net. On the right are also the View buttons for retrieving the primary access key that you will need to set up a client application to access your blob storage. With these two pieces of information, you should be able to view your data.

For uploading and maintaining your files in blob storage, I use Cloud Storage Studio from Cerebrata which is excellent, but not free. There are free storage explorers available, such as the Azure Storage Explorer from CodePlex and the Cloudberry Explorer for Azure Blob Storage.

You should be good to go. Now go read the article on how to actually put your ClickOnce deployment in your new storage account, and start racking up those pennies.