Saturday, August 27, 2011

Migrating a Web Application to Azure: Step 4

Moving the application to Windows Azure

 

A New Project

The first step is to add a new cloud project to the solution.

create_new_cloud_project

Ensure that you do not add any web or worker roles.

We will convert the existing web application within the solution to a Web Role in the Azure Project.

Right Click on the ‘Roles’ folder in the Azure Project, select ‘Add’ and then ‘Web Role Project in solution…’.

Select the web application – in this case ‘SharPix_Step2’

add_web_role

After adding the project as a Web Role, it should look like this:

web_role_added

Right-Click on the ‘SharPix_Step2’ role and select ‘Properties’

In this dialog, under normal circumstances, you should set Instance count to at least 2 to enable fail-over and scaling, and you would pick an appropriate VM size.

Also, we will start by using the Compute and Storage Emulators, so specify ‘UseDevelopmentStorage=true’ as the Diagnostics storage account.

web_role_properties

Running In Emulator…

Visual Studio comes with a tiny taste of the cloud built-in, in the form of the Storage and Compute Emulators.

Simply running our new Azure Project gives us:

web_role_on_compute_emulator

Note the URL and the port number. This is no longer the Visual Studio Development Web Server, but the Compute Emulator in action. Examining the Windows Tray shows us that the emulators are running….

compute_emulator_is_running

To the cloud!

In order to push the Azure Project to our cloud environment, we need to configure Visual Studio and set up our credentials to ensure that we carefully control access to our Azure environment.

Right-Click on the Azure Project and select ‘Publish’. We could use previously issued certificates here, or issue a new one for this project by selecting ‘Add’.

publish_settings

Create a New Certificate, and fill in the details required.

credentials_create_new

Visual Studio creates a new certificate and stores it in a temporary, obscure, folder. Copy the path from this dialog onto your clipboard and head over to the Windows Azure Management portal.

copy_certificate_path

Click on ‘Management Certificates’, select the Azure Subscription you want to deploy to, and select ‘Add Certificate’ from the right-click context menu.

add_management_certificate

Once the certificate is uploaded, select and copy the Subscription ID from the portal and fill it into (3) of the Windows Azure Project Management Authentication dialog shown above. Give the Project some reasonable name and click ‘OK’

After dispatching all the other dialogs, you will be left with the first ‘Publish Windows Azure Application’ dialog. Ensure you have selected a Production Environment, and specify the storage account to use.

ready_to_publish

Hurry Up and Wait

Clicking ‘Publish’ on the dialog above begins the deployment process, which can easily take 15 minutes or more. During this time, some information is relayed through to Visual Studio about the actions being taken and their various statuses.

deployment_in_process

When the deployment is complete, click on the ‘Website URL’ link, or view the deployment in the Server Explorer and select ‘View in Browser’ from the right-click context menu.

The application finally appears. Note the URL is now that of an Azure cloud application.

in_the_cloud

In the Management Portal, expanding the Azure Subscription will show the Deployment node and all the compute instances fired up in the production environment. In our case, we have just one instance, but we could add more.

in_the_cloud_mgmt

And there it is. A fully local web application that is now running in the cloud and using cloud-based blob and database storage.

Next we’ll talk about federating authentication to this application.

 

blogBling_150x150_02333

Migrating a Web Application to Azure: Step 3

Getting rid of file access

One issue to watch out for with an application in the cloud is file access.

File-Access in a highly-elastic environment such as Azure is generally a bad idea because it reduces the ability for a request to be correctly handled by multiple server instances. To combat this, generally, all access to the file system should be changed to access Azure storage, which does scale across multiple server instances.

In our example, we have contrived to have a picture stored in the database, but cached on the file-system on its first use, and subsequent access is to the cached file.

Local Application, Images from Server Files

We have code that looks like this in the original code:

public ServerPath EnsureImage(Picture picture)
{
// ensure the directory exists
var directoryPath = EnsureDirectory(RelativePathToImagesDirectory);

// now ensure the file exists
var filePath = EnsureFile(
directoryPath,
picture.OriginalFilename,
_path =>
{
using (var stream = new FileStream(
_path.Absolute,
FileMode.OpenOrCreate,
FileSystemRights.TakeOwnership | FileSystemRights.Write,
FileShare.None,
1024,
FileOptions.None))
{
stream.Write(picture.Image.ToArray(), 0, picture.Image.Length);
}
});

return filePath;
}

internal ServerPath EnsureFile(ServerPath root,
string filename,
Action<ServerPath> fileCreateFunc)
{
var path = new ServerPath(Path.Combine(root.Relative, filename), Server.MapPath);

if (!(File.Exists(path.Absolute)))
{
fileCreateFunc(path);
}

return path;
}

which results in


images_from_filesystem


Note that the web application is still running locally, and the images refer to files located at relative paths within the server.


To remove the dependency on the file-system, we can use Azure Blob Storage to store the cached files.


The Rise Of The Blob…


Blob storage Azure is very cool. It presents a REST-based API to upload, tag, list and retrieve unstructured binary data like images, documents and videos.


So we can switch the application to interact with the Azure Blob store, referring to the images from the storage in the cloud.


To do this, we use the Azure storage account we created earlier.


configure_blob_storage


The important pieces of information to capture are the Access Key (you get this when you click on the button with the orange outline), and the Azure storage account name which is highlighted.


We then initialize access to the blob storage account and container from within the application:

public void Initialize()
{
if (CloudStorageAccount == null)
{
CloudStorageAccount = CloudStorageAccount.Parse("AccountName=cos204;AccountKey=<put_your_key_here>;DefaultEndpointsProtocol=http");
}

if (CloudBlobClient == null)
{
CloudBlobClient = new CloudBlobClient(CloudStorageAccount.BlobEndpoint, CloudStorageAccount.Credentials);
}

if (ThumbnailsContainer == null)
{
ThumbnailsContainer = CloudBlobClient.GetContainerReference("thumbnails");
}

ThumbnailsContainer.CreateIfNotExist();

if (ThumbnailsContainer.GetPermissions().PublicAccess != BlobContainerPublicAccessType.Container)
{
ThumbnailsContainer.SetPermissions(new BlobContainerPermissions
{PublicAccess = BlobContainerPublicAccessType.Container});
}

if (ImagesContainer == null)
{
ImagesContainer = CloudBlobClient.GetContainerReference("images");
}

ImagesContainer.CreateIfNotExist();

if (ImagesContainer.GetPermissions().PublicAccess != BlobContainerPublicAccessType.Container)
{
ImagesContainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Container });
}
}

What we are doing here is initializing the Blob Storage infrastructures and creating containers for Thumbnails and Images.


It’s important to note that the demo code shows a hardcoded Azure Connection String just to simplify the code snippet for reference. Normally this would be hidden away in a configuration file.


Local Application, Remote Images


We can now replace the file-access code shown above with its Azure Blob equivalent.

public ServerPath EnsureImage(Picture picture)
{
var filePath = EnsureBlob(
ImagesContainer,
picture.OriginalFilename,
_blob =>
{
var blobStream = _blob.OpenWrite();
try
{
blobStream.Write(picture.Image.ToArray(), 0, picture.Image.Length);
}
finally
{
blobStream.Flush();
blobStream.Close();
}
});

return filePath;
}

internal ServerPath EnsureBlob(CloudBlobContainer blobContainer,
string filename,
Action<CloudBlob> blobCreateFunc)
{
var blob = blobContainer.GetBlobReference(filename);

if (blobContainer.ListBlobs().FirstOrDefault(_blob => _blob.Uri.AbsoluteUri == blob.Uri.AbsoluteUri) == null)
{
blobCreateFunc(blob);
}

return new ServerPath(filename, blob.Uri.AbsoluteUri);
}

With this implementation of EnsureImage(), we get:


images_from_blob


Pretty cool.


We now have a web application running on the local server, with data in the cloud, caching files and referencing Azure Blob storage also in the cloud!


Inspecting Blob Storage


While developing and debugging this stage of the migration, it’s useful to see exactly what is being stored in the Azure Blob storage.


The Windows Azure Management Portal does not have a handy tool to inspect the structure and contents of the Azure Storage account, so we turn to some other tools to do that.


The pack of Windows Azure Tools for Visual Studio 2010 v1.4 enables a storage account browser, which can be configured with the storage account and the key as before, allowing for full access to the storage account.


azure-storage-browser


We can use this to ensure that the blob storage account is structured as we expect, and filled with the contents we expect.


Next, we’ll move the application itself to Azure.


blogBling_150x150_02333

Friday, August 26, 2011

Migrating a Web Application to Azure: Step 2

Migrating the database to SQL Azure

Now that we have a local web-application with a database, and a SQL Azure instance up and running, we can start the application migration by moving the database to SQL Azure.

SQL Azure is a modified version of SQL Server 2008 R2, and there are some small, but significant limitations on the SQL DDL commands that can be run on Azure. See here and here for more information.

The upshot is, if you already have a local SQL Server database, then you’re really much better off using some specialized migration tools to move it to Azure. The tool of choice for us is the SQL Azure Migration Wizard off codeplex.

Download and install the latest version of this tool on your development box. You’ll thank the tool-developer later!

Fire up the tool, and select “SQL Database” under “Analyze / Migrate”

sql_azure_mw_0

Select the local database server which hosts the instance you want to migrate

sql_azure_mw_1

Select the database(s) to migrate in turn.

In our case, we will have to migrate both the ASPNETDB and PICTURES databases.

sql_azure_mw_2

Click through the dialogs, and migrate database object present in the database.

sql_azure_mw_3

The Migration Wizard has created the script to use for the migration, and will now require your credentials to migrate to. This is where you fill in the details from the SQL Azure instance screen in the previous step.

sql_azure_mw_4

Let’s let the migrator create a PICTURES database on the Azure Server

sql_azure_mw_6

…and begin the migration work

sql_azure_mw_7

…and we are done!

sql_azure_mw_8

The Azure portal shows the two databases created and ready for use.

sql_azure_portal

Now, let’s hook up the application we wrote to use these databases in the cloud. To do this, we point the connection strings in the Web.Config of the web application to the databases in the cloud.

Thusly:

web_config_2

And that’s it. Here’s the application running locally but with the data in the cloud.

localapp_remotedata

I’ve created a new album called “Clouds” now, and uploaded three new pictures. If we look at the Azure database instance and look at the data in the PICTURES instance, we see the data there:

data_in_the_cloud

Next, we’ll talk about setting up the Azure workspace so we can move our application there…

blogBling_150x150_02333

Migrating a Web Application to Azure: Step 1

Setting up your Azure workspace

So we have a working web-application which we want to move to Azure.

The first thing to do is to get a Windows Live ID and line up one Windows Azure subscription and one SQL Azure subscription.

Sign into windows.azure.com with your Live ID

azure_homepage

Click on the “Hosted Services, Storage Accounts and CDN” button on the bottom left panel, then on “Hosted Services” on the top left panel.

Right-Click on your Azure Subscription in the main panel and select “New Hosted Service”

new_hosted_service

Choose not to deploy at this stage!

Similarly create a Storage Account on the same subscription.

new_storage_service

Now create a database server on the SQL Azure Subscription.

new_sqlazure_database

Ensure you set the firewall rules to include both your machine’s IP address and other Azure services. Your SQL Azure instance will need to be accessed from the Windows Azure instance,

setting_firewall_rules_after

Once you create the database server, you should make a note of the following pieces of information:

  • The subscription id
  • Your administrator login and password
  • The instance name, and the fully-qualified database server DNS name

database_server_ready

Now we have Windows Azure and SQL Azure instances set up for use.

Next we’ll migrate our database to SQL Azure.

 

blogBling_150x150_0233

Thursday, August 25, 2011

Migrating a Web Application to Azure: Step 0

Creating a traditional, locally run web application

Let’s start with a simple, traditional web application.

This is a contrived application, built specifically for demonstrating the issues we want to address in the process of migrating to Azure.

Please do not consider this application as indicative of following best-practices for web application development!

Also, the purpose of this web application is not to wow anyone with a slick user interface! :)

Let’s imagine a site where someone logs on, creates a photo album or two, and uploads a few images to each album.

Prerequisites

You will need the following applications and tools to follow along the process of migrating an application to Azure

  • Visual Studio 2010 (SP1 strongly recommended)
  • SQL Server 2008 R2; you’ll be using SQL Server Management Studio
  • Windows Azure SDK 1.4

We’ll introduce a few more tools along the way, but we can get started with this.

Steps

Let’s create this application the simplest way possible:

First, create the ASPNETDB Application Services database on the SQL Server 2008 instance. You may need to run aspnet_regsql.exe from the .NET framework directory.

aspnet_regsql

Then create a basic web application in Visual Studio:

create_web_application

Modify the Web.Config on the web application to point the Application Services Providers to our database.

non_local_aspnetdb

Pressing F5 to run/debug the web application should fire up the default application, and allow you to create an account to authenticate against in future. The default home page after logging in should look like this:

default_home

To create the picture album site, we create a new database with this simple schema:

pictures_schema

Note that for this demonstration, we will store the uploaded picture in an image column on the Picture table, in the database.

We’ll use Linq 2 SQL to create a data-model for our application.

When we’re done with adding the Linq2Sql classes, the connectionStrings collection in our Web.Config looks like:

connection_strings

Now we’ll actually develop the application, and let’s say we finally land up with:

sharpix

Let’s also assume that the application contains, for the sake of this demonstration, the following code to extract the binary data from the database and cache the file on the file system, so that the images on the rendered page refer to the cached file:

var relativePathToDirectory = "~/.cache";

// ensure the directory exists
var absolutePathToDirectory = Server.MapPath(relativePathToDirectory);
if (!Directory.Exists(absolutePathToDirectory))
{
Directory.CreateDirectory(absolutePathToDirectory);
}

// now ensure the file exists
var relativePathToFile = Path.Combine(relativePathToDirectory, picture.OriginalFilename);
var absolutePathToFile = Server.MapPath(relativePathToFile);

if (File.Exists(absolutePathToFile)) return absolutePathToFile;

using (var stream = new FileStream(
absolutePathToFile,
FileMode.OpenOrCreate,
FileSystemRights.TakeOwnership | FileSystemRights.Write,
FileShare.None,
1024,
FileOptions.None))
{
stream.Write(picture.Image.ToArray(), 0, picture.Image.Length);
}

Conclusion


We have a rudimentary, but fully functional web application that runs on our local web server in the traditional manner.


We will need to consider the specific changes to make when we want to migrate this application to the cloud.


PS:


We’ll put the source code on github and stick the link in here just after the talk.


blogBling_150x150_023

Migrating a Web Application to Azure: Introduction

 

This is a series of posts relating to the details of the talk Mahesh Krishnan and I will be giving at TechEd Australia 2011. You can follow along in this series of posts for more details and gotchas that we can’t cover in the 60 minute talk at TechEd!

Here are the details of the talk:

We’ll be taking a contrived, but simple, traditional data-driven web application, and outlining the issues to consider, and steps to take, to move the application to Windows Azure/Sql Azure.

We’ll show you how to set up your Azure subscription, migrate your database to Sql Azure, manage session state with Azure’s Session State Manager, move file-system based actions to Windows Azure blob storage, and secure your application with Azure’s ACS 2.0 Federated Authentication.

We’ll show you what tools you need and how to use Visual Studio 2010 SP1 to simplify the process of migrating.

There’s some code, but mostly we’re going to be discussing issues, tips and tricks.

See you there!

blogBling_150x150_02