Tuesday, November 6, 2012

Diagnose node.js apps hosted in IIS with iisnode-debug header

The iisnode project allows hosting node.js applications in IIS on Windows. The recent v0.2.0 release not only added support for WebSockets, but also enhanced the diagnostics capabilities of iisnode. This post describes how you can use the new iisnode-debug HTTP response header to get insights into the state of your node.js application.

The iisnode-debug header

The iisnode v0.2.0 module can now add an iisnode-debug HTTP response header to every node.js HTTP response it sends (including WebSocket handshake response):

image

If you look closely at the value of the iisnode-debug header, you will notice it is a URL with several interesting pieces of information included in the URL fragment. Although the diagnostics information can be gleaned directly from inspecting the value of the URL fragment, a more human friendly visualization is provided when you navigate to that URL in the browser, as shown below (the bit.ly URL resolves to a page hosted on GitHub).

The iisnode-debug header contains information about: image

  • Processing time. Latency of processing this HTTP request (time to first byte of response).
  • Named pipe connection retry count. Number of times iisnode had to repeat the attempt to create a named pipe connection to a node.exe process to transmit the request. A number greater than zero may indicate an overloaded server. A number equal to the value of the maxNamedPipeConnectionRetry configuration setting for messages that activate a new node.exe process may indicate the application is taking a long time to initialize before it establishes a listener.
  • HRESULT. The Win32 error code of processing this HTTP request by iisnode. Any value other than 0 indicates a failure. This helps in diagnosing issues with failed requests.
  • Server DNS name. The DNS name of the server to help identify the server handling the request; useful in scaled out scenarios.
  • w3wp.exe PID. The PID of the IIS worker process. IIS worker process that hosts the iisnode module and manages one or more node.exe processes. If you notice the PID of the IIS worker process changing over time, it may indicate a fatal failure in iisnode itself which leads to termination of the IIS worker process.
  • node.exe PID. This helps identify which server/process was handling the request, which is important in scaled out scenarios. Changing PIDs over the course of multiple requests also indicate process recycling, which may point to an issue with the application itself (e.g. uncaught exceptions that terminate node.exe, only to be re-created by iisnode).
  • Memory usage. This is the working set and pagefile memory consumed by the IIS worker process (w3wp.exe) and the node.exe process that handled the request. This data may help detect memory leaks.
  • Active node.exe processes serving this application. Number of node.exe processes created by iisnode to handle the node.js application. iisnode can create multiple node.exe processes and load balance incoming requests between them to allow multi-core CPUs to be fully utilized.
  • Active HTTP requests in this application. Number of active HTTP requests across all node.exe processes that handle this node.js application.
  • Active HTTP requests in this node.exe process. Number of active HTTP requests handled by the node.exe process that processed current request (current request is included in this number).
  • Total node.js requests processed by w3wp.exe. The total number of HTTP requests targeting node.js applications handled by this IIS worker process.
  • Environment. This includes the version of iisnode on the server, full DNS name of the server, and path to the node.exe.

Getting access to most of the information above was previously possible only with advanced tools and direct access to the server. Thanks to the iisnode-debug header, you can now conveniently access this information from the browser even if your application is running in shared hosting environments.

How to enable the iisnode-debug header

The iisnode-debug header is by default disabled for performance and security reasons. To enable the iisnode-debug header, set the value of the debugHeaderEnabled property in iisnode.yml or web.config to true:

image

Check out the other iisnode.yml or web.config settings iisnode offers in the configuration sample.

Other debugging and diagnostics features in iisnode

Besides the new iisnode-debug header, iisnode continues to offer other diagnostics and debugging features for node.js applications hosted in IIS. Check out the following:

Debugging node.js applications hosted in IIS
Using ETW traces
Logging

Enjoy!

Thursday, November 1, 2012

How to use WebSockets with node.js apps hosted in iisnode

Note: if you are interested in hosting socket.io WebSocket applications in IIS using iisnode, check out the more recent post at http://tomasz.janczuk.org/2013/01/hosting-socketio-websocket-apps-in-iis.html

The recent release of iisnode v0.2.0 enables using WebSockets in node.js applications hosted in IIS 8.  This functionality requires Windows Server 2012 or Windows 8. To read more about iisnode in general check out my previous post.

Getting started

After installing iisnode v0.2.0, get a sample WebSocket application from https://github.com/tjanczuk/dante (if you are not a Git person, you can also download a ZIP):

git clone https://github.com/tjanczuk/dante.git

Next, download the node.js dependencies and set up an IIS application in IIS 8 that points to the downloaded code:

npm install
setup.bat

Lastly, navigate to http://localhost/dante/server-faye.js and enjoy Dante’s Dive Comedy, Canto 1, streamed to you over WebSockets though IIS and iisnode, once stanza every 2 seconds:

image 

Under the hood

If you have a closer look at server.js, you will notice the application uses the faye-websocket module to establish a WebSocket server, just like a self-hosted node.js WebSocket application would:

var WebSocket = require('faye-websocket')
, http = require('http');

var server = http.createServer(handler);

server.addListener('upgrade', function(request, socket, head) {
var ws = new WebSocket(request, socket, head);
// ...
});

function handler (req, res) {
// ...
}

server.listen(process.env.PORT || 8888);

In fact, you could take this application and run it self-hosted using node.exe without any changes at all.

The iisnode module uses the functionality enabled in IIS 8 on Windows Server 2012 and Windows 8 to expose the HTTP Upgrade mechanism to the node.js application. Modules like faye-websocket, ws, or socket.io implement the WebSocket protocol on top of the HTTP Upgrade mechanism and expose WebSocket functionality to the application.

Using WebSockets in a node.js applications running in iisnode requires that – contrary to what one would expect – websockets are disabled in web.config:

<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="server-faye.js" verb="*" modules="iisnode" />
</handlers>
</system.webServer>
</configuration>

This is required because IIS 8 provides its own implementation of the WebSocket protocol that builds on top of the HTTP Upgrade mechanism. If the IIS 8 WebSocket module remained enabled, it would conflict with the WebSocket implementation provided by the node.js application itself in the form of one of the node.js modules, e.g. faye-websocket, ws, or socket.io. The IIS 8 WebSocket module is used to enable WebSocket functionality in ASP.NET applications.

So where does it leave you?

The release of iisnode 0.2.0 closes the last major functional gap between self-hosting and IIS hosting node.js applications on Windows: the availability of WebSockets. You can now host your socket.io application in IIS 8 using WebSockets as opposed to falling back to HTTP long polling. Note that WebSocket functionality is only supported on IIS 8 running on Windows Server 2012 or Windows 8. WebSocket on!

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.