Monday, June 25, 2012

Ideal platform for running node.js applications

I have recently conducted a poll on Twitter to get and idea about the features people expect from an ideal platform for hosting web applications written in node.js. I asked only one question: “What features do you expect from a platform for hosting node.js web applications?”. This was followed by a list of 19 features I was interested in researching; for each feature people could choose one of four answers: “I don’t care”, “Weak advantage”, “Strong advantage”, and “Would not use a platform without it”. This post presents the results at the time 243 responses were gathered.

The overall ranking

I ranked the features by assigning the scores as follows: for every “I don’t care” answer a feature was given 0 points, for every “Weak advantage” 1 point, for “Stong advantage” 2 points, and finally for “Would not use a platform without it” 3 points. The rank value represents the sum of points from all responses for a given feature:

Screen Shot 2012-06-25 at 1.38.19 PM

The deal breakers

Below are the features for which more than 20% of respondents answered “Would not use a platform without it”:

The most desired features in a node.js hosting platform

The underdogs

Below are the features for which more than 20% of respondents answered “I don’t care”:

Screen Shot 2012-06-25 at 1.59.27 PM

What do you think?

What do you think of this data? Is there a feature that was not on the list but you care deeply about? Do you expect different features from production and development environment?

Wednesday, June 13, 2012

Performance of hosting node.js applications in iisnode vs self-hosting on Windows

In this post I am sharing high level, general observations related to performance implications of choosing one of the two major ways of hosting node.js HTTP applications on Windows.

Node.js HTTP applications can be run in two ways on Windows today:

  • by self-hosting the application using the node.exe process directly on top of a TCP socket (similarly to the most common way of running node.js applications on other operating systems),
  • by hosting the application in the Internet Information Services (IIS) web server using the iisnode module.

Besides performance, there are other considerations for choosing one method or the other. You may want to review some of the benefits of hosting node.js applications in IIS. If you intend to host your node.js application in Windows Azure, make sure to also read up on the three ways of hosting node.js applications in Windows Azure.

Four reasons you should distrust this post (aka disclaimer)

  1. The measurements were taken using node.js v0.6.6 and iisnode v0.1.13, and both of these technologies continue to rapidly move forward. It is likely that the same measurements done on the most current versions would yield different results.
  2. The scenarios measured may not represent what your application is doing. There is a rather dramatic difference in the results depending on the scenario below, and your actual app is unlikely to closely match any of these scenarios.
  3. I have developed iisnode, why would you trust me to objectively talk about its performance?
  4. Buts. The area of performance measurements yields itself very well to “but”-type of arguments. But the scenario is not real. But the machine is not like a machine I like better. But the payload is too small/large. You get the idea. So in the spirit of transparency you can see the test code, you can repeat the measurements, you can add your own tests (and make a pull request) if you think you have a useful scenario to measure.

Results

The table below shows comparison of throughput between self-hosted node.exe and IIS+iisnode+node.exe:

Screen Shot 2012-06-13 at 3.03.43 PM

Unless otherwise noted below, all measurements were taken at server CPU utilization > 90%. The configuration involved one quad core Windows 2008 server with node.js v0.6.6 and iisnode v0.1.13. Depending on scenario, one or two WCAT client machines were required to saturate the server. Clients and server were connected to the same switch but were not on private network.
 
[1] See test code. In this scenario node.js application returns a simple “hello, world” plaintext response to an HTTP GET request. This is the only scenario that uses a single node.exe instance (both self-hosted and IIS hosted). Given the single-threaded nature of node.exe, the multi-core server CPU is never fully utilized. However, the node.exe process has consistently utilized > 23% of CPU, which corresponds to almost full utilization of a single core of the quad-core server.
 
[1.1] Although in this scenario iisnode achieved better throughput than self-hosted node.exe, it was accomplished with almost twice as large CPU utilization (~60% in case of iisnode compared to ~30% in case of node.exe).
 
[2] See test code. This scenario uses the same node.js “hello world” application as scenario #1, but it utilizes 4 node.exe processes to saturate the CPU on the quad core server. In case of self-hosting node.exe, the built-in cluster functionality is employed. In case of iisnode, the built-in capability to spawn and route to multiple node.exe processes per application is used.
 
[3] See test code. This scenario simulates using node.js to serve a web site using express - one of the most popular MVC frameworks for node. The web site consists of an HTTP endpoint that dynamically generates HTML that displays a randomly generated order information using the jade rendering engine. The HTML refers to a static CSS file. As part of each WCAT transaction, one request is made to the HTML endpoint that generates dynamic content and the another to get the static CSS file. In case of self-hosted node.js application, the static file is served by the express framework using the connect.static middleware (which is built into express and a most likely mechanism to be used by someone serving static content from express). In case of IIS, requests for static content are actually not handled by iisnode at all – a URL rewrite module causes that request to be handled by the native static file handler (which plays to the “side by side with other content types” benefits of iisnode).
 
[4] See test code. This scenario simulates using node.js to implement web APIs: HTTP endpoints that generate dynamic content. In this particular case we are reusing the order generation and HTML rendering endpoint from scenario #3, without including a request for static CSS file in the WCAT transaction.

Interpretation

IIS+iisnode does nicely in a mixed content scenario (Web site)

Scenario #3 represents an end to end web site with node.js using the express MVC framework: some of the content is dynamically generated (dynamic HTML generated from a model), and some is static (CSS, potentially images). Serving static content from node.js is slow enough to more than offset any IIS+iisnode overhead in the dynamic content generation part of the application, resulting in the overall IIS+iisnode throughput 305% larger than self-hosting node.exe. This scenario is a good fit for IIS+iisnode as combines the most efficient aspects of both technologies into one convenient package.

IIS rocks with serving of static content

As scenario #3 shows, IIS+iisnode beats self-hosted node.js in serving static content by a very large factor. It is to be expected that a native file handler implementation would perform much better than any implementation in a managed environment like node.js. The kinds of applications that benefit from this are applications that serve static content as a substantial portion of their transactions.

IIS+iisnode add substantial overhead in dynamic content scenarios (Web APIs)

Scenarios #2 and #4 demonstrate that IIS+iisnode introduce substantial CPU overhead in processing request that require dynamic content generation in a node.js application. These scenarios represent a class of “Web APIs” – HTTP endpoints that are geared towards dynamic content generation, e.g. JSON, XML, ATOM, RSS, but also dynamic HTML.

As the amount of CPU intensive work required to generate the response in the application code increases, the IIS+iisnode overhead becomes less pronounced. On one extreme of CPU intensity we have scenario #2, with extremely lightweight application logic. In that case IIS+iisnode overhead is over 100%, resulting in throughput degradation to 49% compared to self-hosted node.exe. Scenario #4 is a reasonable approximation of the CPU intensity of an MVC application that applies some business logic to the model before rendering the results to the client. This scenario shows smaller IIS+iisnode overhead with throughput reduced to 73% of self-hosted node.exe.

Three ways of deploying node.js apps to Windows Azure

In this post I compare and contrast three ways of deploying node.js applications to Windows Azure to help you choose a method that is best suited to your requirements.

Windows Azure is an application hosting platform operated by Microsoft that supports a variety of application technologies: from ASP.NET, PHP, node.js, to Java and Python. In case of node.js applications, you have at least three ways of hosting it in Windows Azure. They differ with the features of the runtime, deployment experience, and management and diagnostics capabilities. The picture below shows the common and distinctive aspects of using Windows Azure Worker Role, Windows Azure Web Site, or git-azure.

Three ways of deploying node.js applications to Windows Azure

Windows Azure Web Site is an exciting new feature of Windows Azure announced recently. It provides a shared hosting environment in which your node.js application is hosted in the Internet Information Services (IIS) web server using the iisnode technology; a given VM is hosting apps from multiple tenants. The key advantage of Windows Azure Web Sites is the ability to deploy your application using Git to a Git repository provided by Windows Azure itself. Creation of a new application as well as subsequent updates take seconds. The runtime environment does not support WebSockets. Given that Web Sites operate in a shared hosting environment, you also do not get administrative access to the machine (e.g. no RDP or SSH). You can access logs generated by the node.js applications using FTP. If you are developing your node.js application on a Mac, you can use command line tools from Windows Azure SDK for node.js to manage your Windows Azure services, create apps, etc. If you are using Windows to develop your app, you have a choice of WebMatrix or Visual Studio to deploy your app. You can also develop and deploy online using http://c9.io.

In contrast to the shared hosting environment of Windows Azure Web Sites, the Windows Azure Worker Role provides you with your own VM with administrative access using RDP (from a Windows client machine). Deploying applications to Windows Azure Worker Role requires provisioning of that VM which takes minutes rather then seconds. Subsequent updates of the application are also substantially longer than in case of Windows Azure Web Sites. Node.js applications running in Windows Azure Worker Role are self-hosted (as opposed to hosted in iisnode), which does not provide the benefits of hosting in IIS, but on the other hand improves performance in a number of scenarios, enables WebSockets, and has smaller potential of application compatibility issues. If you are developing your node.js application on a Mac, you can use the command line tools from Windows Azure SDK for node.js to deploy to Windows Azure Worker Role. If you are developing on Windows, you can use corresponding PowerShell toolset, or deploy from WebMatrix or Visual Studio. Similarly to Windows Azure Web Sites, you can also develop and deploy online from http://c9.io.

The git-azure project attempts to consolidate elements of the Windows Azure Worker Role and Windows Azure Web Site environment and add a few of its own to create a unique environment for running node.js applications in Windows Azure. git-azure enables deploying multiple node.js applications into a single instance of Windows Azure Worker Role using Git from Mac. You retain the administrative access to the VM using RDP offered by Windows Azure Worker Role, but you can also use SSH for a more convenient access from the Mac. SSH allows you to open a remote console or remotely execute scripts on your VM. In git-azure, multiple node.js applications are self-hosted behind an HTTP and WebSocket reverse proxy that is part of the git-azure runtime environment. All applications are accessible on port 80 and 443 with the use implicit or explicit routing rules. git-azure is tightly integrated with a Git repository where your applications reside. The repository is external to git-azure (e.g. GitHub). Initial deployment of git-azure is similar to deploying node.js applications to Windows Azure Worker Role – it requires provisioning of your own VM and takes minutes. After that, however, adding and modifying applications with a simple ‘git push’ takes seconds with the use post receive hooks, similar to the characteristics of the Windows Azure Web Site. Git-azure provides real time access to logs generated by your applications and the git-azure runtime. The logs are streamed over WebSockets to a web browser a client terminal console. Since applications are self-hosted, WebSockets (both secure and non-secure) are supported. Some other distinctive features of git-azure are support for running multiple node.js engines side by side, SSL by default, and support for specifying custom X.509 credentials per application. When you use git-azure, you develop and maintain your applications using the common set of tools and workflow for node.js apps (i.e. likely your favorite text editor + GitHub), while git-azure provides command line extensions of the Git toolchain to facilitate deployment of your app to Windows Azure. Read more about git-azure or watch a 7 minute inroductory video in the Develop on Mac, host on GitHub, and deploy to Windows Azure post.

My Photo
My name is Tomasz Janczuk. I am currently working on my own venture - Mobile Chapters (http://mobilechapters.com). Formerly at Microsoft (12 years), focusing on node.js, JavaScript, Windows Azure, and .NET Framework.