Category Archives: Azure

Scale out, not up… Cloud Architecture 101

scaleA common question that I get is how to cut down on one’s Azure bill. People will come to me because they are finding a way to control their spend in Azure while not hurting their service levels. Most of these folks are big proponents of the cloud because of how agile they can be and the fact that it’s got geo-replicated content and traffic and so on.

The first time that I saw this question, I was thinking that this could be tough to tackle as Azure’s pricing is fairly aggressive until I saw their architecture. And it turns out that in most cases, it’s the same issue.

A very common architecture is two large web role instances or so in front of a small worker role instance with some storage plus a SQL Azure database. The basic problem here is that the two large instances means that their unit of scale is a large instance which is an 4 core box with 7 gig of memory that costs about $345 a month to run. This is not leveraging cloud computing. There are definitely times where you need a big iron box but for 99% (made up statistic) of web apps, it’s overkill. Actually, overkill is the wrong term, it’s scaling vertically by throwing bigger hardware at a problem rather than what the cloud is really good at which is scaling horizontally.

The fundamental difference between architecting for cloud verses architecting for old school on premise or fixed contract hosting is that in the old world you had to architect and build for the maximum and hope you never hit it. In the new world of cloud computing, you architect for scaling out horizontally and build for the minimum. This means building small stateless servers that can be added or thrown away on an hour by hour basis.

The fix to these customer’s cost issues is simple, move from 2 larges into how ever many smalls you need and then scale up or down as needed.

The reason that they were running 2 larges rather than 2 smalls is that they are concerned about traffic spikes and the site going down. I completely get that and there are a number of great solutions to this issue. We don’t “auto-scale” automatically in Azure. The reason for this is simple, we charge your for instances that are spun up so it’d be in our interest to aggressively spin up new instances and charge you for them. To avoid even the appearance of impropriety, we don’t auto-scale. However, we give you all of the tools to write your own auto-scaling or manage it remotely.

How do you know how many instances you should be running? Go to the Windows Azure portal and look at your current usage. There’s a ton of diagnostics available through the portal. You should go spelunking there and see what all they have. Some folks are running as low as 1-2% utilization whereas we are pushing for folks to try and run on average between 70 and 80% utilization. In a traditional data centre, we’d never never want for that to be our “normal” for fear of spikes but in Azure, your spikes can be soaked up by the rest of the infrastructure.

Once you figure out where your normal should be, build that out and then use some of the tools to scale up or down as needed.

Mobile tools:

http://udm4.com/iPhone/CloudTools_for_Windo-701342. That’ll give you health stats on your instances and then you can turn them on and off from the phone.

http://mobilepcmonitor.com/ – will let you know when your site has any issues at all. X amount of memory being used, X number of users, server goes down and the like. Clients on iphone, windows phone, windows 8, windows 7 and so on.

 

Autoscale with your own code:

http://archive.msdn.microsoft.com/azurescale – auto-scaling yourself sample all.

http://channel9.msdn.com/posts/Autoscaling-Windows-Azure-applications – Windows Azure Application Block that does auto-scaling for you.

http://channel9.msdn.com/Events/WindowsAzure/AzureConf2012/B04 – more great content on how to do this yourself.

 

Third parties to manage your scale:

http://www.paraleap.com/AzureWatch offers monitoring and auto-scaling.

http://www.azure-manager.com/ – does what it says on the tin. Manages azure for you.

http://www.italliancegroup.com/ – does a managed service/partnership where they manage your infrastructure in Azure.

 

In short, if you are looking at cloud computing, make sure that you architect for the right kind of scaling…

Custom Search with Azure Mobile Services in JavaScript

image I’ve published my first little Windows 8 app using the Azure Mobile Services in JavaScript. It was incredibly quick to get up and running and more flexible than I thought it would.

The one thing that was tricky was that I’m using JavaScript/HTML5 to build my app and since I don’t have Linq in JavaScript, doing a custom date search was difficult. Fortunately I got to sit down with Paul Batum from the Azure Mobile Services team and he learned me a thing or two.

I already knew the backend of Azure Mobile Services was node.js. What I didn’t realize is that we can pass in a javascript function to be executed server side for a highly custom search the way that we can with Linq from C#. The syntax is a little weird but it works a treat.

itemTable.where(function (startDate, endDate) {
            return this.Date >= endDate && this.Date <= startDate;
        }, startDate, endDate)
    .read()
    .done(function (results) {
        for (var i = 0; i < results.length; i++) {
           //do something interesting
        };


Notice that inside the where function, I’m passing in another function. This function gets passed back and operates server side. The slightly wonky part is that the function has to accept the parameters that you pass in as well as you have to pass the variables that will be passed to this function. So reading that sample carefully, see that we’re passing three variables to the server side including the function and then the two actual variables that we want to pass to the function that executes on the server.

This allows for some awesome flexibility, well beyond custom date searches. 🙂

Using Windows Azure Storage from the Windows Phone

If you haven’t found Cloud Cover, it’s a great series on Channel9 that covers a lot of great Azure topics. What I particularly like is that it’s shows a lot of very practical knowledge things and doesn’t assume a tremendous amount of knowledge.

I found this one particularly useful with the amount of mobile development that I’ve been doing recently.

Join Wade and Steve each week as they cover the Windows Azure Platform. You can follow and interact with the show at @CloudCoverShow.

In this episode, Wade walks through the NuGet packages for Windows Azure storage and Windows Phone, highlighting how easy it is to interact with blobs, tables, and queues, both directly against storage and securely through proxy services.

Activating BizSpark Azure Accounts

A question that I’ve been asked a number of times recently is how to activate an MSDN Azure account and more specifically, how to do it with a BizSpark account. To make it easy, I thought I’d blog that here.

For an up to date list of benefits you should visit http://www.microsoft.com/windowsazure/msdn-benefits/ but currently it’s as follows:

Subscription Level BizSpark/Visual Studio Ultimate
with MSDN
Visual Studio Premium
with MSDN
Visual Studio Professional
with MSDN
Compute 1,500 hours of the Small Instance 1,500 hours of the Extra Small Instance 750 hours of the Extra Small Instance
Storage 30 GB 25 GB 20 GB
Storage Transactions 2,000,000 1,000,000 250,000
SQL Azure 5 GB 1 GB 1 GB
Access Control Transactions 500K 200K 100K
Service Bus Connections 5 5 2
Data transfers 35GB (WW) Out
35GB (WW) In
30GB (WW) Out
30GB (WW) In
25GB (WW) Out
25GB (WW) In
Annual Savings** $3100 $1300 $800

 

Signing up for BizSpark

2011-04-27_1021

Starting up, if you are a start-up (defined as less than 3 years old, less than $1 million in revenue, privately held and producing technology as your primary monetization) you should be on BizSpark. BizSpark gives you access to all of the Microsoft technologies that you’d need to develop your applications such as Windows, Azure, Visual Studio, Office (in case you need to integrate with it) and more. Just go to http://www.bizspark.com and click Apply Now.

2011-04-27_1022

If you have an existing LiveID, you can use that but the reality is that I recommend that you create a specific LiveID for the start-up because what happens if the person who originally signed up leaves the company? Or is out on a day when something needs to be done on the account? For that reason, I recommend creating a specific account for your BizSpark management.

2011-04-27_1023

I recommend, partly because of the number of lawyers in my family, that you read the terms and conditions but at the end, if you agree, there are two individual agreements that you need to agree to before you click next.

One of those is the BizSpark Startup Agreement and the other is the EULA.

Once you fill out the rest of the wizard, it goes into a process on our end. If you are in Ireland, that registration goes through a two phase approval process. The first phase is with a Network Partner and the second phase is currently me. 🙂

2011-04-27_1038

Once you are signed up, you can log into My BizSpark and click on the Get your Free Software link which will show you a link to MSDN. Reality is that it’s just pointing to MSDN and you can go there directly if you like.

You’ll just need to sign in there with a LiveID that’s associated with a BizSpark member.

Adding new developers to a BizSpark Account

2011-04-27_1041Quick side note is that I’ve also been asked a number of times how to add additional developers to a BizSpark startup. Find the Manage section of the left hand navigation and find the Members link underneath that. Then you put in the new developer’s name and email address. That does not have to be their LiveID – it can be any email address. There will be an acceptance link in the email that will require the person to sign in with their own LiveID to access the bits and all.

Activating Your Azure Benefits from MSDN

2011-04-27_1045Once you sign into MSDN and go to the “My Account” section, you should see the “Windows Azure Platform” link. This link will take you to the Windows Azure signup process and walk you through a longish wizard. At the end of that, you will be able leverage all of the benefits of MSDN on Azure.

One thing to warn you about at this point is that the Windows Azure signup does require a credit card to cover any overages. I recommend that you closely monitor your usage to make sure that you don’t go over. 🙂

2011-04-27_1052Now, once you’re signed up for the Azure benefits, you can simply go to http://windows.azure.com to manage your account and deploy applications. The one portal serves as your management portal for your services, data, SQL Azure and any other services you’re signed up for such as Connect.

Have fun playing with Azure!

Windows Azure Toolkit for Windows Phone 7

WinPhoneAzureThe Windows Azure Toolkit for Windows Phone 7 is a starter kit that was recently released out to CodePlex. Wade Wegner, one of my former team mates when both of us were in Central Region, is the master mind behind this fantastic starter. 

This starter kit is designed to make it easier for you to build mobile applications that leverage cloud services running in Windows Azure.

Screencast

In the screencast, you’ll get a great little walkthrough of the starter kit and how to get your first Windows Phone 7 application with a Windows Azure backend up and running. The toolkit includes a bunch of stuff including Visual Studio project templates that will create the Windows Phone 7 and Windows Azure projects, class libraries optimized for use on the phone, sample applications and documentation.

Why Windows Azure

Windows Azure is Microsoft’s Platform as a Service (PaaS) offering that allows you to build and scale your application in the cloud so that you don’t have to build out your local infrastructure. If you are selling an application in the Windows Phone 7 Marketplace and really don’t know how many customers you’ll end up with, you might need to scale the backend dramatically to meet the demand. 

 

What you’ll need

Hopefully obviously you’ll need an Azure account and the tools to build and deploy the solution. The tools include one of the versions of Visual Studio (either Express which is free or higher), the Windows Azure Toolkit and then obviously the starter kit itself. I also recommend looking at Expression Blend for doing your Windows Phone 7 design and the like.

Good Luck!

By looking through the resources on the Windows Azure Toolkit for Windows Phone 7 site, you’ll see lots of great little tutorials and getting started guides.

Let me know how you’re getting on with the toolkit and what you’ve done with it. I’d like to see and possibly blog about it all…

Zend SimpleCloud and Azure

image I’ve been playing with Zend’s SimpleCloud API for the webcast that I’m doing with Zend today. I started with the Zend Framework Quickstart tutorial but changed out the backend to hit the Azure Tables and such (well kinda – I used Zend Studio 8 Beta 2 and didn’t use the ZF tool but I still created a little guestbook). I’m going to expand this example to include blob storage and queues as well in the near future but at the moment, I’m just going to hit the Azure Tables.

update – here are the slides for the presentation:

To get started, I downloaded and installed the Zend Framework CE 1.10 and Zend Studio 8 Beta 2. Then I downloaded and installed the Windows Azure SDK. imageThe last bit that I needed was the Windows Azure 4 Eclipse which will install inside of Zend Studio since it’s built on Eclipse. To install it, open up Zend Studio/Eclipse and select Help | Install New Software to open up the dialog. Then click Add… and fill in the location as http://www.windowsazure4e.org/update. Click OK, select the Windows Azure for Eclipse Toolkit and follow the rest of the wizard to install it. At this point, I’ve got all of the software installed that I need to install and am ready to start coding.

Creating the Project

Before I create the project, a quick tip is that it’s a lot easier to work with IIS if you move the your Eclipse Workspace to c:\users\public\ZendWorkspace (I’m on Windows 7 so that’s where my public documents are). One more quick step is that I give IUSER Read and Execute permissions on the workspace.

imageOnce I’ve moved my workspace, in Zend Studio, select File, New Zend Framework Project.

Name the project SimpleCloudDemo.

Select “Create new project in Workspace”. I tried creating the project on a local server to skip a few steps but that didn’t work so well as you have to be an administrator to write to the c:\inetpub\wwwroot location. Instead, we’ll just map a virtual directory in IIS in a few moments.

Make sure that Zend Framework default project structure is selected (should be the default).

Click Finish. This will create basic project structure that you’ll need to get started. The Zend Framework is a MVC style framework.

To finish setting up the project we need to include the framework bits and the API bits so that we have everything in a nice portable folder. Copy in the C:\Program Files\Zend\ZendServer\GUI\library\Zend directory to [project dir]\library.

Lastly, download the SimpleCloud Api from http://simplecloud.org/download and unzip it to the [project dir]\library directory.

Mapping the IIS Virtual Directory

Now we want to be able to test and make sure that everything is installed correctly and that the project works. To do this, we’re going to map a IIS virtual directory.

image Open Internet Information Services (IIS) Manager and expand the tree on the left hand side until you find the default web site.

Right Click on the Default Web Site and select Add Virtual Directory…

Fill out the Alias with something simple to remember such as simpleclouddemo and fill in the Physical path with the directory to [your project directory]\public. Since I moved my workspace up above, the full Physical path that I entered is c:\users\Public\ZendWorkspace\SimpleCloudDemo\public

image Now, browse to the virtual directory at  http://localhost/simpleclouddemo.

The one other thing that I’ll do that’s IIS specific is create a URL_Redirect rule that will make sure that the Zend Framework actually gets all of the calls rather than the calls just going into the IIS bit bucket. The easiest way to do that is to create a file called web.config in the public directory.

<?xml version="1.0"?>
<?configuration>
  <?system.webserver>
    <?rewrite>
      <?rules>
        <?rule name="Main URL Rewrite Rule" patternsyntax="Wildcard">
          <?match url="*" />
          <?conditions>
            <?add negate="true" input="{REQUEST_FILENAME}" matchtype="IsFile" />
            <?add negate="true" input="{REQUEST_FILENAME}" matchtype="IsDirectory" />
          <?/conditions>
          <?action url="index.php" type="Rewrite" />
        <?/rule>
      <?/rules>
    <?/rewrite>
  <?/system.webserver>
<?/configuration>

At this point you should have the project up and running. Now we’re ready to start slinging code.

Creating the Model and Azure Table

We’re going to dive right in and start creating the model and the Azure Table.

The first thing that we’re going to create is the Guestbook model class itself. Create a new PHP file named GuestBookModel.php in the /application/models directory as follows.

<?php
// application/models/GuestbookModel.php
 
class Application_Model_Guestbook extends Zend_Service_WindowsAzure_Storage_TableEntity
{
	/**
	* @azure comment Edm.String
	*/
	public $comment;	
	/**
	* @azure created Edm.String
	*/
	public $created;
	/**
	* @azure email Edm.String
	*/
	public $email;
}

Couple of things that are interesting here.

  1. Notice that the class extends (read inherits for those of you that don’t do PHP heavily) Zend_Service_WindowsAzure_Storage_TableEntity. This parent class gives us the other required fields such as a PartitionKey, RowKey, TimeStamp and the like.
  2. Next, notice the @azure comments in front of each of the variables. This gives typing information to the Azure Table storage engine for comparisons, sorting and storage optimization. The possible choices there are:
Property Type Details
Edm.Binary An array of bytes up to 64 KB in size.
Edm.Boolean A Boolean value.
Edm.DateTime A 64-bit value expressed as UTC time. The supported range of values is 1/1/1601 to 12/31/9999.
Edm.Double A 64-bit floating point value.
Edm.Guid A 128-bit globally unique identifier.
Edm.Int32 A 32-bit integer.
Edm.Int64 A 64-bit integer.
Edm.String A UTF-16-encoded value. String values may be up to 64 KB in size.

The next thing to do is create the GuestBookMapper in the application\models directory.

<?php
// application/models/GuestbookMapper.php
 
class Application_Model_GuestbookMapper
{
	protected $_cloudTable;
	protected $TABLE_NAME = "guestbook";
	protected $PARTITION_KEY = "guests";
    
    public function setCloudTable()
    {
    	//This constructor takes account parameters for the live azure account
    	//Goes to Dev Storage if you don't pass in any parameters. 
    	$tableStorageClient = new Zend_Service_WindowsAzure_Storage_Table();
		$this->_cloudTable = $tableStorageClient;
    	
        return $this;
    }
    
    public function getTableStorageClient()
    {
    	if (null == $this->_cloudTable) {
            $this->setCloudTable();
    	}
        return $this->_cloudTable;
    }
 
    public function fetchAll()
    {
    	$tableStorageClient = $this->getTableStorageClient();

        if ($tableStorageClient->tableExists($this->TABLE_NAME))
        {
    		return $tableStorageClient->retrieveEntities($this->TABLE_NAME, "", "Application_Model_Guestbook");
        }
    	return null;
    }
    
    public function save(Application_Model_Guestbook $guestbook)
    {
    	$tableStorageClient = $this->getTableStorageClient();
        if (!$tableStorageClient->tableExists($this->TABLE_NAME))
    	{
    		$tableStorageClient->createTable($this->TABLE_NAME);    		
    	}
    	
    	$guestbook->setPartitionKey($this->PARTITION_KEY);
    	if ($guestbook->getRowKey() == null) {
    		$guestbook->setRowKey(uniqid ());
    	}
    	
	$tableStorageClient->insertEntity($this->TABLE_NAME, $guestbook);
    }
  }

As you look at that code, there’s a couple of things to point out.

  1. I could pass in parameters to the constructor of the Zend_Service_WindowsAzure_Storage_Table constructor to give my account information for a Windows Azure storage account but if you don’t pass anything in it defaults to the dev storage account.
  2. In the fetchAll() function,  the second parameter being passed to the retrieveEntities function is a filter parameter. This is where you could pass in the search parameters and/or a partition to retrieve and so on. Regardless of what you pass in, the function attempts to match on those items and returns a collection of items that match.

The next thing is to create the GuestBookController.php in the application\controllers folder.

<?php
/**
 * GuestbookController
 * 
 * @author
 * @version 
 */
require_once 'Zend/Controller/Action.php';
class GuestbookController extends Zend_Controller_Action
{
    /**
     * The default action - show the home page
     */
    public function indexAction ()
    {
        $guestbook = new Application_Model_GuestbookMapper();
        $this->view->entries = $guestbook->fetchAll();
    }
    
    public function signAction()
    {
        $request = $this->getRequest();
        $form    = new Application_Form_Guestbook();
 
        if ($this->getRequest()->isPost()) {
            if ($form->isValid($request->getPost())) {
                $comment = new Application_Model_Guestbook();
                $comment->comment = $form->getValue("comment");
	       $comment->email = $form->getValue("email");
                
	       $mapper  = new Application_Model_GuestbookMapper();
                $mapper->save($comment);
                return $this->_helper->redirector('index');
            }
        }
 
        $this->view->form = $form;
    }
}

Couple of things to point out here as well.

  1. In the indexAction, the fetchAll() call returns the list of entries as a collection and  hands it off to the view.
  2. In the signAction, we’re using the Application_Form_Guestbook which we are about to create. It’s got a little bit of validation but I wouldn’t rely on just that for my business logic but I’m a belt and suspenders kind of guy when it comes to data validation.

The next step is to create the Guestbook.php in application\forms directory.

<?php
class Application_Form_Guestbook extends Zend_Form
{
    public function init()
    {
        // Set the method for the display form to POST
        $this->setMethod('post');
 
        // Add an email element
        $this->addElement('text', 'email', array(
            'label'      => 'Your email address:',
            'required'   => true,
            'filters'    => array('StringTrim'),
            'validators' => array(
                'EmailAddress',
            )
        ));
 
        // Add the comment element
        $this->addElement('textarea', 'comment', array(
            'label'      => 'Please Comment:',
            'required'   => true,
            'validators' => array(
                array('validator' => 'StringLength', 'options' => array(0, 1000))
                )
        ));
 
        // Add a captcha
        $this->addElement('captcha', 'captcha', array(
            'label'      => 'Please enter the 5 letters displayed below:',
            'required'   => true,
            'captcha'    => array(
                'captcha' => 'Figlet',
                'wordLen' => 5,
                'timeout' => 300
            )
        ));
 
        // Add the submit button
        $this->addElement('submit', 'submit', array(
            'ignore'   => true,
            'label'    => 'Sign Guestbook',
        ));
 
        // And finally add some CSRF protection
        $this->addElement('hash', 'csrf', array(
            'ignore' => true,
        ));
    }
}

The only thing to point out here is that this is a standard Zend Framework form.

The last thing that we absolutely need to do is create the two views, one for viewing and one for signing. The first one that we’ll create is index.phtml in application\views\scripts\Guestbook

<!-- application/views/scripts/guestbook/index.phtml -->
 
<p><a href="<?php echo $this->url(
array(
'controller' => 'guestbook',
'action' => 'sign' ),
'default',
true)
?>">Sign Our Guestbook</a></p> Guestbook Entries (<?php echo count($this->entries) ?>): <br /> <table>
<tbody>
<?php foreach ($this->entries as $entry): ?>
<tr>
<td><?php echo $this->escape($entry->email)?></td>
<td><?php echo $this->escape($entry->comment)?></td>
</tr>
<?php endforeach ?>
</tbody>
</table>

And next we’ll create the sign.phtml in application\views\scripts\Guestbook.

<?!-- application/views/scripts/guestbook/sign.phtml -->
 
Please use the form below to sign our guestbook!
 
<?php
$this->form->setAction($this->url());
echo $this->form;

There are other things that we could do but that all that we need to do for the moment. I’ll extend this example in the future.

Now, if you run the application and browse to http://localhost/simpleclouddemo/guestbook

If you get the error “Application errorexception ‘Zend_Http_Client_Adapter_Exception’ with message ‘Unable to Connect to tcp://127.0.0.1:10002. Error #10060: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.” – it’s because you need to launch the Development Fabric and specifically start the storage bit.

Once that’s done, you should see the guestbook as follows:

Empty

Then you can sign the guestbook as follows:

sign

And then it will redirect you back the guestbook which will look as follows:

firstentry

This is the bulk of what I demoed during the webinar. I’m going to continue to expand this demo as time goes on

Webinar on Oct 20, 2010 with Microsoft/Zend

imageI’m looking forward to starting this new webinar series that I’m launching in partnership with Zend about running PHP in general and Zend in particular on Microsoft Azure.

My goal, as I’m writing the demos today after posting this, is to go through the Zend Guestbook quick start and then port that to run in Azure and leverage that platform. I’ll be posting the full technical write-up here once I get done.

From the Zend web site:

Join a webinar on Cloud Computing with Zend Framework and Windows Azure. In this session, we’ll take a technical overview of Windows Azure Data Storage which can be used both inside and outside of your cloud application and the Windows Azure computing which can be leveraged to scale your application horizontally. We’ll write a small application with the Zend Framework and get it up and running in Azure so that we can dive deep into the individual parts in future webinars.
Join this webinar to learn how to take your application to the next level.

Register

It’s important to note that this is the first of a series so we’re going to do an overview across the board this time and then we’ll dive deep into things such as the data access layers or architecting for scaling horizontally across multiple instances in the future.

Resolving PHP Version Conflicts while Developing for Azure

A little while back I wrote a blog post titled Easy Setup for PHP On Azure Development. One of the things that I touched on is the PHP version conflicts. I had a much better idea which I’ve tried and have working so I thought I’d blog that here. What I had you doing in the Easy Setup for PHP On Azure Development is renaming the directory for PHP from something like C:\PHP or C:\Program Files\PHP to something else so that it wasn’t in the %PATH% so there wasn’t a conflict.

The Fix

Reality is that we don’t have to do that. Instead, we can all co-exist happily on the same box. In short, what we’re going to do is load the local version of PHP from our box into the dev fabric rather than using the one that’s bundled with the Eclipse plug-in. The way that we’re going to do that is by using the web.config to specify the location on the local disk where our PHP install is.

That web.config looks something like this:

<?xml version="1.0"?>
<configuration>
  <system.webServer>
  
    <!-- DO NOT REMOVE: PHP FastCGI Module Handler -->
    <handlers>
      <clear />
      <add name="PHP via FastCGI"
           path="*.php"
           verb="*"
           modules="FastCgiModule"
           scriptProcessor="c:\program files\php\php-cgi.exe"
           resourceType="Unspecified" />
      <!--add name="PHP via FastCGI"
           path="*.php"
           verb="*"
           modules="FastCgiModule"
           scriptProcessor="%RoleRoot%\approot\php\php-cgi.exe"
           resourceType="Unspecified" /-->
      <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
    </handlers>
    
    <!-- Example WebRole IIS 7 Configation -->
    <defaultDocument>
      <files>
        <clear />
        <add value="index.php" />
      </files>
    </defaultDocument>
    
  </system.webServer>
</configuration>

Notice that I’ve commented out the original handler that setup the processer with the %RoleRoot%\approot\… We’ll need that when we go live but for now, we’ll use the one that’s actually using the hard path on my local disk.

The exciting part about it is that we’ll be able to use our own version of PHP with all of the extensions that we normally use and configured exactly to taste.

Testing Local

The other exciting thing is that you can actually test any of your WebRole code against your local IIS rather than having to deploy it to the DevFabric every time you want to test. Deploying to the DevFabric takes time and so I’ve found myself taking more time and slinging just a little more code than I should before doing my testing. Against my local IIS box, I’m able to just refresh the browser and see instant results. I still definitely recommend running in the DevFabric because it’s as close to the real environment as you’re going to get at the moment.

image To test against your local IIS with the same exact source code and folders, simply set up the directory as a Virtual Directory. To do that, you need to do one of two things. You can open up the IIS manager and add it that way or you can use Powershell to do it.

In IIS manager, expand the navigation tree down to find the web site that you want to deploy your virtual directory on (typically this is “Default Web Site”) and right click. Then select Add Virtual Directory and fill out the wizard with the alias (e.g. myproject will end up with http://localhost/myproject) and the physical path that you want to use.

If you decide to go with the PowerShell option and do it from the command line, there’s a great cmdlet (Powershell script) called New-WebVirtualDirectory that you can leverage. Make sure that you read the instructions on how to Import All Modules.

The Catch

Now, the issue that you’ll have with this is that when you do actually go to deploy to the cloud, you’ll need to either retest with the version of PHP that’s bundled by default by the Eclipse tooling or make your deployment package by hand with the command line tools.

My recommendation is rolling your own package with the command line tools. Really all you need to do is use CSPack (and possibly CSRun to test locally) from my blog post at Windows Azure Command Line Tools.

Additionally, The great news there is that there’s some great tools available for you at http://azurephptools.codeplex.com/.

Wrap up

I’m much happier with this solution than I was with the whole renaming the directory hack. It worked but it was a pain when switching between regular and Azure development. This way, regular and Azure development are seamless.

Miami 311: Built on Windows Azure

This is a cool use of Azure. The city of Miami tool their “311” data around potholes, trash pickup issues, recycling issues, broken sidewalks and the like and put that data in Azure. The next step is that they leveraged Bing Maps and Silverlight to visualize those issues spread on a map of the city.

The solution takes advantage of virtually unlimited storage and processing power, provides the ability to quickly address service requests and implement updates even during peak times such as hurricane season. If things change, the City can bring the solution on site or move to a physical facility, all based on  need and cost-effectiveness.

As a result, residents logging on to Miami 311 can see on average 4,500 issues in progress – not represented as a ‘list’, but located on a map in relation to other projects in their neighborhood .  A simple click on the map allows them to easily drill down to more and more specific details if they want.

In short, they have turned what used to be represented by a meaningless list of data into useful information, and created  actionable and consumable knowledge that is relevant to the citizens of Miami. For Miami, their ‘service call to the city’ becomes an interactive process they can follow – and the City has a new tool to manage and deliver outcomes.

When the city made the move to the web, they chose tools they knew and software they trust. The Microsoft Windows Azure cloud platform made it easy to do, and they used both Bing mapping and Silverlight to build a user friendly front end.

According to Port25 (Miami 311: Built on Windows Azure – Port 25: The Open Source Community at Microsoft), it took two people 8 days to implement the whole system and they are going to open source their solution so that other cities can leverage it. I haven’t seen yet where and how they are going to release it but I’ll keep you posted if I find out.

Creating a Simple PHP Blog in Azure

In this post, I want to walk through creating a simple Azure application that will show a few pages, leverage Blob storage, Table storage and generally get you started doing PHP on Azure development. In short, we are going to write a very simple PHP Blog engine for Azure.

To be very clear, this is not a pro blog engine and I don’t recommend using it in production. It’s a lab for you to try some things out and play with PHP on Azure development.

If you feel like cheating, all of the source code is available in the zip file at http://www.joshholmes.com/downloads/pablogengine001.zip.

0. Before you get started, you need to make sure that you have the PHP on Azure development environment setup. If you don’t, please follow the instructions at Easy Setup for PHP On Azure Development.

image

Create a Windows Azure Web Project

1. To accomplish this, click on File | New | Project.

2. In the New PHP Azure Web Project page, name the project PABlogEngine (for PHP on Azure Blog Engine).

3. Next you need to select Windows Azure Data Storage. Notice that we’re not selecting SQL Storage. We are going to be using Table and Blob Storage for this project.

4. Click Finish

Creating a Table Entity in PHP

The next step is to get a little setup stuff done. We are going to be using Entities to put into our Table.

1. Create a file called PABlogPost.php. This is going to contain our Entity that we are going to put into our Azure Table storage.

2. Fill out the PABlogPost.php as follows:

<?php
/*
 * Include the Windows Azure Table Storage helper class from the 
 * Windows Azure for PHP SDK
 */
require_once 'Microsoft/WindowsAzure/Storage/Table.php';

class PABlogPost extends Microsoft_WindowsAzure_Storage_TableEntity
{
    /*
     * Notice the Doctrine style comments, some of which, 
     * such as $ImageType, have typing information. 
     * Anything that doesn't have a type is stored as a string. 
     */
    
    /**
     * @azure Title
     */
    public $Title;
    
    /**
     * @azure Description
     */
    public $Description;
    
    /**
     * @azure Author
     */
    public $Author;
    
    /**
     * @azure pubDate
     */
    public $pubDate;
    
    /**
     * @azure Image
     */
    public $Image;
    
    /**
     * @azure ImageUrlOriginal
     */
    public $ImageUrlOriginal;
    
    /**
     * @azure Type
     */
    public $ImageType;
    
    /**
     * @azure Size Edm.Int64
     */
    public $ImageSize;
    
    /**
     * @azure Visible Edm.Boolean
     */
    public $Visible = false;
}
?>

Setting up the utilities

The next step is to get a couple more utilities in place prior to actually writing our application. Specifically, we have two utility functions that we need to hit on and some system wide values.

1. Create a file called utility.php

2. Add the following two values to it.

$BLOG_TABLE = "blogposts";
$BLOG_POSTS_PARTITION = "posts";

We will use these whenever we are going to be accessing the table and or partition. This will let us quickly change them in one place if we ever need to.

The next thing that we need to do is have a consistent way to create our Table Storage Client as we’re using it on more than one page.

3. Add a function called createTableStorageClient as follows:

/**
 * Create Table Storage Client for table operations using account defined in ServiceConfiguration file
 *
 * @return Microsoft_WindowsAzure_Storage_Table New storageclient for Azure Storage Table
 */ 
function createTableStorageClient()
{
  if (isset($_SERVER['USERDOMAIN']) && $_SERVER['USERDOMAIN'] == 'CIS')
  {
    $host = Microsoft_WindowsAzure_Storage::URL_CLOUD_TABLE;
    $accountName = azure_getconfig('AzureCloudStorageAccountName');
    $accountKey = azure_getconfig('AzureCloudStorageAccountKey');
    $usePathStyleUri = true;
    
    $retryPolicy = Microsoft_WindowsAzure_RetryPolicy::retryN(10, 250);
    
    $tableStorageClient = new Microsoft_WindowsAzure_Storage_Table(
                              $host,
                              $accountName,
                              $accountKey,
                              $usePathStyleUri,
                              $retryPolicy
                              );
  }
  else
  {
    $tableStorageClient = new Microsoft_WindowsAzure_Storage_Table();
  }
        
	return $tableStorageClient;
}

4. Lastly, we will need a unique identifier. I’m going to follow Maarten’s lead from the sample code that he’s produced and create a UUID with the following function.

// Generate UUID
function generateUuid($prefix = '')
{
	$chars = md5(uniqid(mt_rand(), true));
	$uuid  = substr($chars,0,8) . '-';
	$uuid .= substr($chars,8,4) . '-';
	$uuid .= substr($chars,12,4) . '-';
	$uuid .= substr($chars,16,4) . '-';
	$uuid .= substr($chars,20,12);
	return $prefix . $uuid;
}

Saving to Windows Azure Table Storage and Windows Azure Blob Storage

There are actually several steps to creating a new post. The first is gathering the information. Next is inserting the post into the table. After that, inserting any images et all into the blob storage, then updating the table if needed with that new information.

1. Create a file called CreateNewPost.php.

2. Insert any template/html code that you want to make it look decent but the primary thing that you need in this page is a form that will accept the correct data do a post back to a file called newpost.php as follows:

<form enctype="multipart/form-data" method="post" action="NewPost.php">
<input value="1048576" type="hidden" name="MAX_FILE_SIZE" />
Title:
<input name="posttitle" /><br />
Description:
<textarea rows="5" name="postdescription" type="text"></textarea><br />
Author:
<input name="postauthor" /><br />
Choose an image to upload:
<input type="file" name="imageUpload" /><br />
<br />
<input value="Create Post" type="submit" />
</form>

3. Create a new file called newpost.php

<?php
// Note that this code is NOT safe against various attacks and should be
// used for demonstrating the concepts of the application only.
// NEVER deploy to production without building correct checks!

// 1. Specify include path and include Windows Azure SDK for PHP
set_include_path( get_include_path() . PATH_SEPARATOR . $_SERVER["RoleRoot"]);
require_once 'utility.php';
require_once 'PABlogPost.php';

require_once 'Microsoft/WindowsAzure/Storage/Table.php';
require_once 'Microsoft/WindowsAzure/Storage/Blob.php';

// 2. Instantiate services and make sure table and blob container exist
$tableStorageClient = new Microsoft_WindowsAzure_Storage_Table();
if (!$tableStorageClient->tableExists($BLOG_TABLE))
{
	$tableStorageClient->createTable($BLOG_TABLE);
}

$blobStorageClient = new Microsoft_WindowsAzure_Storage_Blob();
if (!$blobStorageClient->containerExists($BLOG_TABLE))
{
	$blobStorageClient->createContainer($BLOG_TABLE);
	$blobStorageClient->setContainerAcl($BLOG_TABLE, Microsoft_WindowsAzure_Storage_Blob::ACL_PUBLIC);
}

// 3. Add a record in Windows Azure Table Storage
$newpost = new PABlogPost($BLOG_POSTS_PARTITION, generateUuid());
$newpost->Title = $_POST["posttitle"]; 
$newpost->Description = $_POST["postdescription"]; 
$newpost->Author = $_POST["postauthor"]; 
$newpost->Image = $_FILES['imageUpload']['name'];
$newpost->ImageType = $_FILES['imageUpload']['type'];
$newpost->ImageSize = $_FILES['imageUpload']['size'];
$newpost->UrlOriginal = '';
$newpost = $tableStorageClient->insertEntity($BLOG_TABLE, $newpost);

// 4. Upload the image to blob storage
$blob = $blobStorageClient->putBlob($BLOG_TABLE, $newpost->getRowKey(), $_FILES['imageUpload']['tmp_name']);

// 5. Update the post to reflect the new image URL in the table
$newpost->ImageUrlOriginal = $blob->Url;
$newpost= $tableStorageClient->updateEntity($BLOG_TABLE, $newpost);

?>
<h1>New Post up!</h1>
    
<p>
	Your post has been created. Navigate to
	<!-- 6. Show the results -->
	<a href="post.php?id=<?php echo $newpost->getRowKey(); ?>"><?php echo $newpost->Title; ?></a>
	to see your new post.
</p>

Reading from Windows Azure Table Storage

We are almost done. The last thing that we need to do is to show the results for a specific post and to modify the index.php to show all of the posts.

1. Create a new file called post.php. We already referred to this page in the newpost.php file.

2. Fill out this post.php as follows:

<?php
set_include_path( get_include_path() . PATH_SEPARATOR . $_SERVER["RoleRoot"]);
require_once 'utility.php';
require_once 'PABlogPost.php';
// 1. Include the table storage information

require_once 'Microsoft/WindowsAzure/Storage/Table.php'; // 2. Instantiate services $tableStorageClient = new Microsoft_WindowsAzure_Storage_Table(); // 3. Fetch post details $Id = $_REQUEST['id']; $post = $tableStorageClient->retrieveEntityById($BLOG_TABLE, $BLOG_POSTS_PARTITION, $Id); ?> <h1><?php echo $post->Title; ?></h1> <table border="0" cellspacing="0" cellpadding="2"> <tr> <td rowspan="2"> <img src="<?php echo $post->ImageUrlOriginal; ?>" alt="<?php echo $post->Title; ?>" /> </td> <td> <?php echo ' - Title: <b>' . $post->Title . "</b><br/>"; echo ' - Description: ' . $post->Description . "<br/>"; echo ' - Author: ' . $post->Author . "<br/>"; echo ' - Author: ' . $post->Author . "<br/>"; echo ' - pubDate ' - $post->pubDate . "<br/>"; ?> </td> </tr> </table> <a href='/'>Home</a>

There’s a couple of things to notice about this code.

First, notice that we’re not talking to blob storage in the PHP code. All we are doing is putting in a link to the blob with the $post->ImageUrlOriginal. This is because the blob storage is giving us a restful endpoint that we need.

Another thing to notice is that it’s not doing any checks for exceptions. You will want to do that in your code.

3. The last thing that we need to do is the index.php. Fill it out as follows:

<?php
set_include_path(get_include_path() . PATH_SEPARATOR . $_SERVER["RoleRoot"] . "\\approot\\");

require_once 'utility.php';
require_once 'PABlogPost.php';
/**
 * Refer PHP Azure SDK library files for Azure Storage Services Operations
 */
require_once 'Microsoft/WindowsAzure/Storage.php';
require_once 'Microsoft/WindowsAzure/Storage/Table.php';

$tableStorageClient = createTableStorageClient();

if ($tableStorageClient->tableExists($BLOG_TABLE))
{
	/**
	 * Performing queries. Notice that we are not using a filter. 
	 */
	$posts = $tableStorageClient->retrieveEntities(
		$BLOG_TABLE,
		'',
		'PABlogPost'
	);

	echo "Blog posts:<br />";
	foreach ($posts as $post)
	{
		echo '<p>';
		echo '<b><a href="post.php?id=' . $post->getRowKey() . 
			'">' .$post->Title . '</a></b>';
		echo ' - Description: ' . $post->Description . "<br/>";
		echo ' - Author: ' . $post->Author . "<br/>";
		echo ' - Author: ' . $post->Author . "<br/>";
		echo '</p>';
	}
}
?>

imageConclusion

At this point, we have a very rudimentary blog written in PHP on the Azure platform that is using Table Storage and Blob Storage for all of it’s data. Couple of key points to hit on are that this is not using a traditional database.

I will very likely continue to enhance this little toy application over time as I try showing off more and more things in PHP on Azure.

Again, all of the source code is available in the zip file at http://www.joshholmes.com/downloads/pablogengine001.zip.

*Update* Someone was having issues with this one and emailed me. The error that they were getting was:

Fatal error: Uncaught exception ‘Microsoft_Http_Transport_Exception’ with message ‘cURL error occured during request for http://127.0.0.1:10002/devstoreaccount1/Tables?NextTableName=test: 7 – couldn’t connect to host’

Turns out that they had not started the Development Storage service so there was nothing for cURL to connect to in the first place. To start it, start the Development Fabric (the computation engine). Once the Development Fabric is up and running, you will need to right click on the Dev Fabric icon in the system tray and select Start Development Storage Service.

clip_image001

At this point you should be good to go.

BTW – if you actually play with this code, I’d love to hear about your experiences with it either in email at josh (dot) holmes (at) microsoft (dot) com or in the comments below.