A former twenty something in technology

All posts in Azure

nodeIn my previous most I explained how to get started running a node.js application with Azure WebApps. In this post I will note some more advanced features that I would recommend you consider for your project.
  • Routing static files
  • Multiple Instances
  • Slow Initial Render After Deployment (or timeout)
  • Always On & Application Initialization
  • Kudu notifications & Git SHA

Routing Static Files

IIS is handling the requests for your application initially and then proxying requests into node.exe through a named pipe port. Now while node.js is perfectly capable of handling serving up static resources like images, css, html, etc. why burden it. Using a simple IIS rule in your web.config you can just have IIS serve the file directly by passing node.
<rule name="StaticContent">
<action type="Rewrite" url="client{REQUEST_URI}"/>

Multiple Instances

IISNode is capable of spinning up multiple node processes and assigning them each a unique named pipe port that it will round robin serve requests too. Now while node by default is already async and makes good use processing during IO operations. You may still have some CPU intensive sections of your app and node is basically single threaded. Multiple instances of your application will easily allow it to scale and will allow it to tolerate a few application faults without taking everyone down. You can set the nodeProcessCountPerApplication value to acheive multiple node.js instances. These settings can be configured in the web.config but I recommend setting them with the Azure WebApps Application Settings section.

Slow Initial Render After Deployment

Unfortunately Azure WebApps disk IO performance is not wonderful. So for a real world application that contains thousands of node_modules it can take some time for it to read the entire hierarchy into memory before it can start serving HTTP requests. In order for your first request to not timeout in these cases you can extend the namedPipeConnectionRetryDelay timeout (in milliseconds) to something longer than it takes for your application to boot. This will ensure that the first request will wait to the actual response being proxied out to node responds.

Always On & Application Initialization

During a deployment all your node processes will shut down and won't initialize until the next request comes in. Azure WebApps have a feature called Always On which for a Asp.net application will ensure the application pool is kept running and won't spin down when idle -- aka no requests coming in. -- However that is only part of the equation. For IISNode we need to leverage Application Initialization in order to handle a primer request to spin up the node process as well. Beware of SSL. It's important to note that Application Initialization is unable to make HTTPS requests so if you redirect all HTTP requests to HTTPS then you will need to configure at least a specific route that is allowed to handle HTTP requests in order for Application Initialization to work.
<applicationInitialization skipManagedModules="true" doAppInitAfterRestart="true">
<-- Any route that is HTTP accessible -->
<add initializationPage="/warmup" />

Kudu notifications & Git SHA

If you decided to use continuous integration when you push to your repository. Then you probably experienced the mystery if your application deployed successfully or not. Using the Kudu interface you can go to tools > Web hooks. Using a service like Zapier you can configure a service endpoint to receive notifications when deployment is done, successful or failure. Then do what you want with that information. In my case I post it to a slack channel With or without notifications it can often be useful to know exact SHA your application is running. This information is available from Azure WebApps Kudu debug console under the path D:\home\site\deployments\active  A simple file read script will do the trick.
var fs = require('fs');

var filePath = 'D:\home\site\deployments\active');
var version_sha;
fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
if (!err){
version_sha = data.toString();

Running Node On Azure Web Apps

Categories: Azure, nodejs
Comments: No
nodeIf you don't want to manage a virtual machine and just want to take advantage of Azure's salable web app infrastructure for running your node.js application then this post is for you I've broken this guide into a few key areas of pain that I went through getting the configuration right and reliable.
  • Commit your node_modules (*Your choice...but..)
  • Express & IISNode
  • Continuous Integration, SSH & Private Repositories
  • Kudu is Kool
  • Node versions

Commit your node_modules

I've tried pretty much every option that involved not committing your node_modules. This is where I've landed so let me explain the pros and cons I'll get the con out of the way right away. Yes, you're committing all your dependencies, code you didn't write, which will increase the size of your repository. Now on the flip side lets go over the pros:
  1. Deployments are faster. You only have to deploy your repository and you're done. No concerns with running npm install during a deployment and getting a untested version of a dependency.
  2. No concerns with network timeouts or latency when downloading thousands of additional files.
Just because you didn't write it doesn't mean you're not responsible for it. At the end of the day it's your application and you need to take ownership of all facets of it.

Express & IISNode

Azure WebApps come pre-installed with IISNode an open source IIS module allowing you to proxy connections from IIS to Node. Enabling this feature can be done by adding a web.config file to the root if your project with a couple lines of configuration. If you've ever done Asp.net development then a web.config is pretty straight forward to you. But for the node.js folks the web.config is basically an xml based instructions for IIS and .net. In this case it's going to tell IIS what to do with requests and how to route them into node. Beware of named pipes. It's important to know that because IIS is handling the requests on port 80 your node app is actually given a named pipe string for the port instead of a number and that is what IIS will proxy requests through. Hope that gives you a good idea of how to configure Azure WebApps to run node.js and some of the initial brain teaser issues to solve.
<-- Change path to the entry point of your application -->
<add name="iisnode" path="index.js" verb="*" modules="iisnode" />
<-- All of these properties can be overriden at the application level -->
<iisnode node_env="development" loggingEnabled="true" debuggingEnabled="true" logDirectory="..\LogFiles\nodejs" promoteServerVars="HTTPS" enableXFF="true" />

Continuous Integration, SSH & Private Repositories

If you're using GitHub you may be interested in doing continuous integration. Using the Azure setup wizard for continuous integration against your repository will generate a SSH key on that repository. This grants this server access to pull from your repository if it's public or private which is great. It will also add a web hook to kudu to notify the server when a push on your desired branch is done. We now have continuous integration and deployment complete right? Well maybe... Re-assigning SSH Keys A nice touch of Kudu is that it will by default do a git pull --recurse-submodules allowing you to pull any associated sub modules with your project as well. However because the SSH key is only assigned to the primary project you won't be authorized to pull the sub modules by default. You can get around this limitation by logging into your GitHub project and removing the SSH key auto generated by Azure. Then through the Kudu web interface path out to the .ssh directory, D:\home\.ssh and grab the public SSH key. Then add this key to your GitHub account instead of to a specific repository.

Kudu is Kool

Kudu is an open source interface for Azure WebApps that handles deployments and management of your application. It's really awesome actually. But the primary pain comes during the deployment process. During a deployment Kudu will launch a deploy.cmd batch script that you can alter to do any unique operations for your project before and after deployment. Two primary issues you will run into
  • npm install - If you didn't follow my advice about node_modules then Kudu will have to do npm install causes it to make hundreds of requests to install node_modules.
  • Kudu Sync - Is part of the Kudu deployment process. It's job is to copy new or changed files. However it can easily become out of sync and mistakenly think it has already copied the file or it's the same and not replace it.
Maybe I'm just lucky at hitting fringe cases immediately but with a real world project Kudu had my files out of sync after a couple deployments. The good news is because the Kudu deployment script is just a batch script we can do anything you can do with batch. Robocopy I've been a huge fan of robocopy for years and it's my go to tool of choice when ensure files and folders are in sync. Replace:
rem call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 100 -f "%DEPLOYMENT_SOURCE%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
call :ExecuteRoboCopy robocopy "%DEPLOYMENT_SOURCE%" "%DEPLOYMENT_TARGET%" /MIR /MT /R:100 /NDL /NP /NFL /XD ".git" /log:"D:\home\LogFiles\deployment.log"
Then you will have robocopy in charge of keeping your repository in sync with your wwwroot deployments.

Node Versions

You can configure Azure WebApps to use a specific of node by Application setting WEBSITE_NODE_DEFAULT_VERSION to the version you desire. Not all versions are available. I recommend using the Kudu interface to path to D:\Program Files (x86)\nodejs to get a list of all the available versions. Check out my next post on some advanced configurations and some additional recommendations.  

Windows Azure VM Subscription Transfer

Categories: Azure
Comments: No
I successfully managed to transfer my Windows Azure Virtual Machine to a different subscription without losing any files with minimal downtime.

How did I do it?

I followed the steps on the Windows Azure Documentation: How to Capture an Image of a Virutal Machine Running Windows Server
  1. Ran sysprep on my Windows VM (C:\Windows\System32\Sysprep\Sysprep.exe)
  2. Waited about 10 minutes for operation to complete and system shutdown
  3. Clicked Capture
Then UH OH! You're going to delete my virtual machine? But that means I will lose my IP address because there will be no VMs running under that domain. THERE HAS GOT TO BE A BETTER WAY. In fact there is. So what I did was:
  1. Created a new extra small Ubuntu virtual machine and added to an existing virtual machine (the one I was about to capture).
  2. Added Apache quickly to host a web server letting people know I'm down. (sudo apt-get install apache2)
  3. Modified the default index.html (sudo vim /var/www/index.html) and created a nice maintenance message.
  4. Created a new endpoint for port 80 temporarily to the Ubuntu virtual machine.
  5. Back on the primary machine. Started the Capture.
  6. When the capture was finished. I created a new virtual machine utilizing the image I just captured and set the subscription to the one wanted to move too.
  7. VM booted up. I had to re-add my attached disk
  8. Removed Port 80 endpoint from the Ubuntu virtual machine and applied it to the newly created Windows machine.
  9. Shutdown Ubuntu VM (I will keep you around for future maintenance since you no longer cost me money except the small storage charge)
BAM! Site migrated to the new subscription and website is up and running without any loss to data.