Scott Hanselman

"It's just a software issue"- Edge.js brings Node and .NET together on three platforms

April 30, '14 Comments [44] Posted in Learning .NET | nodejs | Open Source
Sponsored By
.NET and node together on three platforms

There was an engineer I used to work with who always said "That's just a software issue." No matter how complex the issue, no matter how daunting, they were confident it could be solved with software.

.NET and C# and NuGet and the community have been making some amazing stuff in the last few years like ScriptCS, Chocolately, Boxstarter. Azure Websites now supports ASP.NET, sure, but also PHP, Python, Java (Tomcat or Jetty or your own container), and node.js. Getting these things to work together has been an interesting software issue. Apps can run side-by-side, but they can't really talk to each other in-process. (Mostly one just moves data between universes over JSON and HTTP when need-be.)

However, Tomasz Janczuk has been working on Edge.js (on Github) for a while now. I showed his work at jQuery Portland last year, but this week he's taking it to the next level. He is creating a wormhole between software universes.

Edge.js now lets you run node.js and .NET code in-process on Windows, Mac, and Linux.

The name is great. An edge connects two nodes, and Edge.js is that edge.

node and .NET connected by edge.js

Here's a node app hello world node app calling .NET. Don't sweat that the .NET code is tunneled inside a comment, this is the Hello World proof of concept.

var edge = require('edge');

var helloWorld = edge.func(function () {/*
async (input) => {
return ".NET Welcomes " + input.ToString();
}
*/});

helloWorld('JavaScript', function (error, result) {
if (error) throw error;
console.log(result);
});

Perhaps you have a bunch of CPU intensive work or algorithms in C#, but you've also got a node.js app that needs the result of that work. Edge can help with that.

You can bring in a CS or CSX file into node like this:

var myCSharpCode = edge.func(require('path').join(__dirname, 'myCSharpCode.csx'));

You can bring code from a .NET DLL into a node.js compiled as well.

var clrMethod = edge.func({
assemblyFile: 'My.Edge.Samples.dll',
typeName: 'Samples.FooBar.MyType',
methodName: 'MyMethod'
});

It's not a hack, it's a clear way to marshal between CLR threads and the V8 (the node Javascript engine) thread. It's also interesting from a comp-sci perspective as the CLR can have many threads and V8 has the one.

nodecsharp

Here's Tomasz's own words:

Edge.js provides an asynchronous, in-process mechanism for interoperability between Node.js and .NET.

You can use this mechanism to:

  • access MS SQL from Node.js using ADO.NET more...
  • use CLR multi-threading from Node.js for CPU intensive work more...
  • write native extensions to Node.js in C# instead of C/C++
  • intergate existing .NET components into Node.js applications

Read more about the background and motivations of the project here.

Now, you might ask yourself, what problem does Edge.js solve? The answer is in the Edge.js FAQ.

Go explore what you can do. Edge goes much further than just C# and Node. It works on Windows, OSX, and Ubuntu but you should just "npm install edge" as there's a node package available.

Have fun! You have a lot more power and flexibility than you think. It's just a software problem.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Introducing node.js Tools for Visual Studio

November 21, '13 Comments [93] Posted in nodejs | Open Source | VS2013
Sponsored By
node.js and Express running in VS

Just when you thought it couldn't be crazier in Redmond, today they are introducing node.js Tools for Visual Studio!

NTVS runs inside VS2012 or VS2013. Some node.js enthusiasts had forked PTVS and begun some spikes of node tools for VS. At the same time the PTVS team was also working on node.js integration, so they all joined forces and made NTVS a community project. NTVS was developed by the same team that brought you PTVS with help from friends like Bart Read from Red Gate (he did the npm GUI), and Dmitry Tretyakov from Clickberry for several debugger fixes & features.

NTVS is open source from the start, and has taken contributions from the very start. It supports Editing, Intellisense, Profiling, npm, Debugging both locally and remotely (while running the server on Windows/MacOS/Linux), as well publishing to Azure Web Sites and Cloud Service.

It's actually pretty freaking amazing how they did it, so I encourage you to download it and give it a try because some of the stuff (even given this is an alpha) is very very clever.

Blank Express Application

Node.js Tools for Visual Studio takes advantage of V8 Profiling API's as well Visual Studio's Reporting features to give you a sense of where your program is spending its time.

NOTE: See that File | New Project dialog up there? Visual Studio organizes things by language, so node.js is under JavaScript. But you've also got Python and Django, iOS and Android via C#, TypeScript, VB, F#, all in Visual Studio.

One of the things that's impressed me about the way they integrated node.js into Visual Studio was that they didn't try to recreate or re-do things that already worked well. It's node, it runs node.exe, it uses the V8 debugger, it uses the V8 profiler because that's what people use. Duh. But, for example, NTVS can take the output from the V8 profiler and display it using the Visual Studio Profiler Reporting Tools. No need to reinvent the wheel, just use the right tool for the job.

Hacking on the Ghost blogging engine with node.js for Visual Studio

Let's look at an example.

From within Visual Studio, go File New Project, click JavaScript, then "From Existing Node.js code."

From Existing node.js Code

Point NTVS to your Ghost folder.

Create from Existing Code

Then tell node.js for VS that the startup file is index.js, hit Next, save the project file and Finish.

Create New Project from Existing Code

At this point, you've got Ghost inside VS.

Random: that since I have Web Essentials I also get a nice split-screen markdown editor as well.

From here, just hit F5 to Debug, or Ctrl-F5 to start without Debugging. Also notice the properties of the Project in the lower right corner there showing the node path and port as well as the Startup File. You can change these, of course.

Ghost inside Visual Studio with NTVS

Here's me running Ghost locally. You can see the path to node, the ghost.js file and my browser.

Running Ghost in VS with node for VS

You'll get good intellisense for completions and help for method signatures.

Intellisense example

Debugging

Node.js Tools for Visual Studio includes complete support for debugging node apps. This includes support for Stepping, Breakpoints, "Break on exception", as well as Locals, Watch, Immediate and Call Stack tool windows.

You can manage Exceptions just like any other language service. See in the dialog below node.js exceptions are listed along with other exceptions in managed and unmanaged code.

Managing Exceptions in node.js for Visual Studio

The debugging still happens like it always has, with the node V8 debugger, except Visual Studio connects to the debugger over another socket (remember, you can even debug node.js remotely running on a Linux or Mac like this!) and translates how V8 thinks into how Visual Studio thinks about debugging. The experience is seamless.

See in this screenshot, you can see node.exe is being debugged, I'm running Ghost. You can see my Call Stack, and the Locals in the Watch Window. I can inspect variables, step around and do everything you'd want to do when debugging a Web App.

Debugging Session of Ghost in VS with Node Tools for Visual Studio

npmVisual Studio

The npm experience is pretty cool as well. Node.js for Visual Studio is always watching the file system so are more than welcome to run npm from the command line or from within the node immediate window and Visual Studio will see the changes.

You can also use the npm Package Management dialog and search the repository and install packages graphically. It's up to you.

npm package management within VS

Here's a package installing...

Installing a module

The physical node_modules and how modules are handled is pure node...VS doesn't touch it or care. However, the Solution Explorer in Visual Studio also presents a logical view on top of the physical view.

image

NOTE: I really like this. I think it has potential and I'd even like to see references in .NET treated like this. The physical and the logical, along with a dependency tree showing NuGet packages. It helped me understand the project much better.

There's lots more. There's an REPL interactive window, and you can just publish like any other web project using the same Publish Wizard that ASP.NET projects use. You can publish node.js apps directly to Azure as well, either with Git or with Visual Studio publishing.

You can also remotely debug node instances running on other machines by starting node with the included Remote Debugging Proxy.

image

node.exe RemoteDebug.js -machineport 5860 script.js

As mentioned, you can do remote debugging between Visual Studio and node running on any server OS.

Conclusion

I'm personally pretty happy with the way that Visual Studio is turning (in a short amount of time, seems to me) into quite the competent language and environment factory.

Node.js Tools for Visual Studio is entirely open source under the Apache license and they welcome contributions and bug reports. It's Alpha and it's early but it's awesome. Go get it. Big congrats to all involved!


Sponsor: Thanks to Red Gate for sponsoring the feed this week! Easy release management: Deploy your .NET apps, services and SQL Server databases in a single, repeatable process with Red Gate’s Deployment Manager. There’s a free Starter edition, so get started now!

Disclosure: FYI, Red Gate does advertise on this blog, but it was a total coincidence that a Red Gate employee helped with node.js Tools for VS. I just found that out today. They are very nice people.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

How to install the nodejs Ghost blogging software on Azure Websites

October 24, '13 Comments [26] Posted in Azure | nodejs | Open Source
Sponsored By
The Ghost Admin running in Azure

Like many folks, I watched the recent Kickstarter for the nodejs-based Ghost Blogging Platform with great interest. There are lots of folks, myself included, who believe that WordPress has jumped from blog to complete and complex CMS, and there's value in a simple platform for "just blogging."

SIDE NOTE: Every time a post something I get at least 4 emails from well-meaning readers about how my spelling and grammar sucks. And I appreciate you all. For a few posts, I'm trying an online service called Grammarly that promises to be 10x better than word processors in proofreading. 10x is like 9 x's more than 1 x and it's clearly a much more bigger number. We shall be seeing how it do. ;)
(Of course, Grammarly HATED this paragraph.)

Ghost is very minimal, evocative of Medium in style and essence. Ghost is basic and clean publishing, plus it's open source and being very actively developed on GitHub. As of the time of this writing, it's version 0.3.3, and I will do my best to keep this blog post up to date. Things are moving fast.

It'd be nice to get Ghost running on Azure, and since it's a reasonably complex node application, it's good exercise for everyone. Jeremiah Billmann and a number of others have been working on some of the small compatibility issues (like image uploads and pathing), and soon we'll be able to get Ghost up and running in just a few commands. Jeremiah has a great writeup here. He and I spent part of the afternoon Skyping and pairing and trying alternate ways to get Ghost running. My instructions are different and not meant to take away from his. There's more than one way to deploy a site.

I'll point out workarounds, and again, remove them (strike them out) as Ghost takes PRs. (BTW, the Ghost Team is SO NICE. So nice.)

Installing Ghost on Azure Web Sites

I'm using Windows, but these commands should also work on Macs.

IMPORTANT CHOICE: You can just go download Ghost at https://ghost.org/download/ and everything comes pre-built.
If you download it, you can SKIP getting Grunt, Ruby, Sass, below. Just get node, and move to the Configuring Ghost before you Deploy section further down!
Otherwise, if you "git clone" like I did, you're doing stuff manually, certainly more than is needed, but perhaps learning more about node.
So, want it prebuilt and ready to go? Download Ghost.
Learning, hacking? git clone https://github.com/TryGhost/Ghost.git.

Prerequisites

To start, you'll want these things locally:

  • nodejs - Get 0.10 or above. Install from http://nodejs.org
    • Then get the node Azure command line
      • npm install azure-cli --g
  • Git - Get it from http://git-scm.com/downloads
  • Get Grunt
    • npm install grunt-cli --g
  • ruby - Get 2.0 or above. Install from https://www.ruby-lang.org
  • Bourbon and Sass. Bourbon brings in Sass.
    • gem install bourbon
  • Get an Azure Trial if you don't have one.
    • You get 10 websites free and can run whatever you want, node, php, ASP.NET, etc.

Setup the Azure Command Line

Connect the Azure CLI (command line interface) to your account like this:

  • azure account download
    • launches browser, sign in, get cert
  • azure account  import
  • [optional] azure account set "account name"

Getting Ghost

You can either download Ghost prebuilt or get the source and build it. Here's both ways. The Source is harder, but I learned some things.

Getting Ghost from Download

Download Ghost and unzip it into a folder.

> azure site create [Site Name] --location "West US" --git
# note that this line setups the "git remote add..." and you can confirm with "git remote show"
> azure site config add NODE_ENV=production
# sets an env var for node, up in azure
> npm install
# get all the modules locally, only needed if you are running locally
> copy con server.js
var GhostServer = require('./index');
CTRL-Z, ENTER
# Ghost uses index.js, not server.js. Make a server.js.

Now, skip over this to the Configuring section. The --git switch above set up your remote git repo in Azure.

Getting Ghost from Source

Now, run these commands from the command line. Read carefully, and think. You can change Site Name, Location. You can confirm the git remote. Things with # are my comments, don't type them. Note the copy con. Don't like it? Use a text editor.

> git clone https://github.com/TryGhost/Ghost.git
> azure site create [Site Name] --location "West US" --git
# note that this line setups the "git remote add..." and you can confirm with "git remote show"
> azure site config add NODE_ENV=production
# sets an env var for node, up in azure
> npm install
# get all the modules locally
> grunt init
> grunt prod
#preps your CSS and JS
> copy con server.js
var GhostServer = require('./index');
CTRL-Z, ENTER
# Ghost uses index.js, not server.js. Make a server.js.

At this point, you have a site running in Azure with nothing in it.

You currently have a local Git repo with a Git Remote pointing to Azure.

Configuring Ghost before you Deploy

Your cloned Ghost includes a config.example.js. I renamed it to config.js and made a few changes.

production: {
url: 'http://YOURSITE.azurewebsites.net/',
mail: {
transport: 'SMTP',
options: {
auth: {
user: 'poop',
pass: 'alsopoop'
}
}
},
database: {
client: 'sqlite3',
connection: {
filename: path.join(__dirname, '/content/data/ghost.db')
},
debug: false
},
server: {
host: '127.0.0.1',
port: process.env.PORT
}
}

Go to the production section, check your URL, your user/pass for mail (mine is invalid, I'll do it later), and check the port: section. Make it "process.env.PORT" which is what Azure uses to get the Port number.

Now open your .gitignore, comment out these lines. enabling you to check in these files and directories.

# /core/client/assets/css
# /core/built
# /core/client/assets/fonts
# config.js

When you ran grunt prod earlier, it built files into /core/built, that's why we need that checked in.

NOTE: Of course, we are using Git for deployment. If you don't want to use Git, you can just FTP the files into Azure.

Deploy

Now, add, commit, push.

> git add .
> git commit -m "hope this works"
> git push azure master

Azure (specifically the Kudu subsystem) will run npm install, so this deployment may take a while. You can watch it live in the Azure Portal if you like.

There's my deployment in the Azure Portal

You can also look at deployments from the command line:

C:\Ghost>azure site deployment list hanselmanghost
info: Executing command site deployment list
+ Getting deployments
data: Time Commit id Status Author Message
data: ------------------- ---------- ------ --------------- ----------------
data: 2013-10-23 15:59:38 783746f6a1 Active Scott Hanselman adding server.js
info: site deployment list command OK

OK. It's deployed...except, today...there's a bug.

The Big Hack as of October 23rd...THIS HAS BEEN CLOSED AND MERGED!

Here's the hack/workaround. There's a node module called Express-HBS that is a handlebars template engine that supports partials. It has a caching bug, but there's been a Pull Request opened for express-hbs with the fix. As soon as that fix gets merged in, this whole workaround just goes away.

But, for now, you need to patch the express-hbs/lib/hbs.js with this version (link to RAW file)

How do you patch this in Azure? You can either FTP it, or use this super-secret Azure Kudu DebugConsole that is public but no one has noticed it yet.

Visit https://YOURSITEHERE.scm.azurewebsites.net/DebugConsole/ in your browser. The name and password are the same as your Git Deployment name and password.

Kudu DebugConsole

Navigate to site/wwwroot/node_modules/express-hbs/lib by clicking folders. Click the Edit button, which brings you to a live multiline textbox. Copy paste the patched hbs.js into the textbox, and click Save.

Once you've patched hbs.js, you're all good. Go hit http://YOURSITE.azurewebsites.net/ghost and sign in.

My ghost blog works

Where are the images for my posts stored? They are right there on the file system where Ghost put them. Here's me remoted into the Azure WebSite with the Kudu Debug Console. There's the images.

Images in Ghost in the Azure Kudu Debug Console

You might not want to scale this website out to more than once instance, as you'll have file contention, but you could certainly scale it up. Since it does so little, I don't see Ghost having much trouble scaling to the average blog's traffic.

Myself, Jeremiah, and lots of other folks are going to work on getting Ghost up and running even easier. Once that hack is gone, there's about 2 or 3 steps could be removed and this will be really quite streamlined. I've got some ideas about using Custom Azure Websites Deployment Scripts to move the Grunt build steps into Azure. They would happen after the push. We'll see!

Have fun, I am! Also, check out http://friday.azure.com, my new show where I learn Azure from the folks that built it...coming soon!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

WebMatrix and node.js: The easiest way to get started with node on Windows

September 16, '11 Comments [24] Posted in IIS | nodejs | WebMatrix
Sponsored By

Tomasz Janczuk and Steve Sanderson are having entirely too much fun. I posted just two weeks ago on Installing and Running node.js applications within IIS on Windows - Are you mad? when Tomasz and the team got node.js running rather nicely under IIS. Now they've got a nice little development environment in WebMatrix.

Cats and Dogs, living together, mass hysteria

Then, Steve and Tomasz decide to share clever thing with us. Well, let me just show you. Remember, this is all in-progress goofing around v0.5 stuff at best but the concepts are sound.

node.js inside WebMatrix. You may start freaking out now.

And then:

Node.js Express Site1 - Microsoft WebMatrix (76)

Hit Run:

Node.js Express Site running on Windows

How can you use WebMatrix to develop node.js applications yourself? With these easy steps:

Isn't it lovely when LEGO pieces snap together so nicely?

Enjoy, Dear Reader.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Installing and Running node.js applications within IIS on Windows - Are you mad?

August 28, '11 Comments [59] Posted in IIS | nodejs | Open Source
Sponsored By

iisnode registering node.js in IIS management Some folks on our team have been working on making node.js work awesomely on Windows. There's a few questions you might have.

First, what's node.js?

If you're not familiar with node.js, it's a new web programming toolkit that everyone's talking about. It's the one that makes you feel not hip if you don't know what it is. Like Ruby on Rails was a few years back. Folks called it "Node" and it's basically server-side JavaScript. The idea is that if you are doing a bunch of JavaScript on the client and you do JavaScript all day, why not do some JavaScript on the server also. One less thing to learn, I suppose.

If you are an ASP.NET programmer, you can think of node.js as being like an IHttpHandler written in JavaScript. For now, it's pretty low-level. It's NOT an HttpHandler, but I'm using an analogy here, OK? Here's a lovely article by Brett McLaughlin that goes into more detail about Node.js and what it is. His subtitle is "Node isn't always the solution, but it does solve some important problems" and that's just exactly it.

UPDATE 1: Why does node.js matter?

Why bother with node at all? There's a number of interesting aspects to node as it sits. It uses a very fast JavaScript engine called V8, but more importantly its I/O is asynchronous and event-driven which contrasts with typical synchronous code.

For example, a naive hello world HttpHandler in ASP.NET that "does some work" for a few seconds (gets a file, accesses a service, etc) could look something like this:

public class SimpleHandler : IHttpHandler 
{
public void ProcessRequest(HttpContext context)
{
Thread.Sleep(2000); //Do something that takes a while
context.Response.Write("Hello from SimpleHandler");
}

public bool IsReusable { get { return true; } }
}

And this is usually fine for most stuff. However, when I push this HARD with a load testing tool and a thousand virtual clients, I can barely get 60 requests a second. The request thread is tied up waiting for the "work" to happen and everyone else gets in line. I'm using up ASP.NET pool. It'd be nice if the work would get handled and someone would "call me back" when it's finished. It's like waiting on hold for tech support. You are effectively blocked as you wait for them to pick up their end. Wouldn't it be nice if they just called you back when they were ready?

ASP.NET has always been able to do things (see this MSDN article from 2003 on Async Handlers) with IHttpAsyncHandler but it's always been a bit hard and almost no one knows about it. With the Async CTP and the Task libraries built into .NET, you can build a nicer abstraction on top of IHttpAsyncHandler. Ayende has a simple example AbstractAsyncHandler (there's many of these out there, including a few in our own tools, some things in MVC, and some things in SignalR (more on that soon)) that we can use to do similar work. This example could also do other more complex and pertinent things like file IO, db IO or calling a web service. This is a naive example that doesn't map exactly to the node one below, but it makes the point. Plus, it's nice to look at.

public class SimpleAsyncAyendeHandler : AbstractAsyncHandler
{
protected override async Task ProcessRequestAsync(HttpContext context)
{
await TaskEx.Delay(2000);
await context.Response.Output.WriteAsync("Hello from Ayende and Scott");
}
}

Pointing the same 1000 virtual clients at this handler gives me 500 requests a second, which makes sense as a request takes 2 seconds to finish. If we were doing I/O or other more complex and long running things than waiting, this scales better than the first example. Doing asynchronous code in .NET as well as parallelism is much easier than before, as evidenced by the two lines of  code above and the simplicity of Ayende's small example. The fact that this kind of thing is easy and elegant in node is an attractive thing about node.

Node loves asynchrony, and uses JavaScript callbacks to provide asynchrony in a pleasant way. You use events and callbacks in JavaScript already on the client, why not use them on the server? Here's an example from Marc Fasel's blog on the topic.

First, some synchronous file work via Marc:

var fs = require('fs'), filenames, i, processId;

filenames = fs.readdirSync(".");
for (i = 0; i < filenames.length; i++) {
console.log(filenames[i]);
}
console.log("Ready.");

processId = process.getuid();

And the same work using an asynchronous pattern that may look familiar!

var fs = require('fs'), processId;

fs.readdir(".", function (err, filenames) {
var i;
for (i = 0; i < filenames.length; i++) {
console.log(filenames[i]);
}
console.log("Ready.");
});

processId = process.getuid();

The I/O happens and the callback function that's dependant on the result is executed when the I/O is finished. Powerful stuff.

Why would I want node.js to run on Windows and IIS?

Tomasz Janczuk is working on the iisnode project lately. You might think that Windows and node don't belong together. "That's just wrong! What are they thinking? I thought IIS was all about .NET?" Well, you may recall I spoke at CodeMash a few years back on IIS7 and PHP and did a screencast showing how IIS7, PHP and FastCGI could push many thousands of requests a second. The IIS folks, the Windows folks, the Azure folks, want to make sure everything runs well on Windows. Remember, we sell Windows, so it's good if it does many things well. ;)

Why bother getting node to run on IIS? Tomasz says it best:

Some of the advantages of hosting node.js applications in IIS using the iisnode module as opposed to self-hosting node.exe processes include:

  • Process management. The iisnode module takes care of lifetime management of node.exe processes making it simple to improve overall reliability. You don’t have to implement infrastructure to start, stop, and monitor the processes.
  • Scalability on multi-core servers. Since node.exe is a single threaded process, it only scales to one CPU core. The iisnode module allows creation of multiple node.exe processes per application and load balances the HTTP traffic between them, therefore enabling full utilization of a server’s CPU capacity without requiring additional infrastructure code from an application developer.
  • Auto-update. The iisnode module ensures that whenever the node.js application is updated (i.e. the script file has changed), the node.exe processes are recycled. Ongoing requests are allowed to gracefully finish execution using the old version of the application, while all new requests are dispatched to the new version of the app.
  • Access to logs over HTTP. The iisnode module provides access the output of the node.exe process (e.g. generated by console.log calls) via HTTP. This facility is key in helping you debug node.js applications deployed to remote servers.
  • Side by side with other content types. The iisnode module integrates with IIS in a way that allows a single web site to contain a variety of content types. For example, a single site can contain a node.js application, static HTML and JavaScript files, PHP applications, and ASP.NET applications. This enables choosing the best tools for the job at hand as well progressive migration of existing applications.
  • Minimal changes to node.js application code. The iisnode module enables hosting of existing HTTP node.js applications with very minimal changes. Typically all that is required is to change the listed address of the HTTP server to one provided by the iisnode module via the process.env.PORT environment variable.
  • Integrated management experience. The issnode module is fully integrated with IIS configuration system and uses the same tools and mechanism as other IIS components for configuration and maintenance.

    In addition to benefits specific to the iisnode module, hosting node.js applications in IIS allows the developer to benefit from a range of IIS features, among them:

    • port sharing (hosting multiple HTTP applications over port 80)
    • security (HTTPS, authentication and authorization)
    • URL rewriting
    • compression
    • caching
    • logging

These are all compelling, but the most interesting bit here, in my opinion, is integration. The iisnode module is a proper IIS module, just like ASP.NET and PHP. This means you can have a single website that has multiple kinds of content. Restated from above:

For example, a single site can contain a node.js application, static HTML and JavaScript files, PHP applications, and ASP.NET applications.

Sometimes folks freak out when I say you can have an ASP.NET WebForms app and a ASP.NET MVC app in the same AppPool as a "hybrid." Frankly, Dear Reader, people don't even realize the power and flexibility of IIS. When you plug in something new like node but run it the way you run other things it inherits all the coolness of the outer container, in this case, IIS.

Fine, you got me, how do I run node.js on Windows?

I'm assuming you are running IIS7.

  • Go download node.exe, and put it in c:\node
  • Go download a build of iisnode.
  • Unzip iisnode's zip into \inetpub\iisnode
    • (that was my idea, not sure if it's the best place)
  • From an Administrator Command Line, run install.bat.

The install.bat will:

  • unregister existing "iisnode" global module from your installation of IIS if such registration exists
  • register iisnode as a native module with your installation of IIS
  • install configuration schema for the "iisnode" module
  • remove existing "iisnode" section from system.webServer section group in applicationHost.config
  • add the "iisnode" section within the system.webServer section group in applicationHost.config
  • delete the iisnode web application if it exists
  • add a new site iisnode to IIS

No warranties! Be careful, you're living on the edge. Remember, you're reading this stuff on some random dude's blog.

WARNING: I couldn't figure out the right permissions for the AppPool and the File System so I wimped out and gave my local AppPool "SYSTEM" permissions. This is awful and totally my fault. I filed an issue on the iisnode GitHub and I'll fix it and update this post when I hear back.

I made a new AppPool just for node, gave it SYSTEM access, then assigned the Node Site to this new AppPool. Your site should look like:

Node Site in IIS7

And if you click on Modules for this Site in IIS7 you should see iisnode as a native module:

Hey, it's iisnode as a native module, just like I said. Crazy.

At this point, you should be able to hit http://localhost/node/helloworld/hello.js and get back:

Hello, world! [helloworld sample]

The contents of which are simply:

var http = require('http');

http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello, world! [helloworld sample]');
}).listen(process.env.PORT);

Lovely.

Fooling around with WCAT (Web Capacity Analysis Tool) and node.

Disclaimer: To be clear, this is so very fooling around. This is just to show that it works and it can do the basics really fast. I'm not doing a benchmark nor am I saying "this works better than this other thing." Remember, they just got started recently porting node itself to Windows, and Tomasz and friends are just beginning their work. So, don't overreach. That said, the preliminary work they are doing is really impressive.

I couldn't help myself. I mean, it's one thing to install a helloworld of some new thing, run it once and go "OK, that runs." It's another to pound it until it says "Uncle." After I got the hello world stuff working, I wanted to do some poor man's stress testing to see what the players involved did.

First, I installed WCAT, a free Web Capacity Analysis Tool from the IIS team.

  1. WCAT 6.3 x86
  2. WCAT 6.3 x64

Warning. This is a command-line only tool and it's really persnickety when you run it. It's confusing and it took me a minute to setup.  Here's the steps I took after installing. This is all from an Administrator Command Prompt. Note also that I'm doing this all on one machine, which is cheesy, but remember, it is a GOM.

  1. cscript //H:Cscript
  2. wcat.wsf –terminate –update –clients localhost
  3. Then I made a folder I called \nodetests and I put these three files in it:

wcat.bat

pushd C:\Users\Scott\Desktop\nodetests
"c:\program files\wcat\wcat.wsf" -terminate -run -clients localhost -f settings.ubr -t nodescenario.ubr -s localhost -singleip -o C:\Users\Scott\Desktop\nodetests
pause

nodescenario.ubr (or call it whatever you want)

This is so basic. It just beats on the four sample applications for a while.

scenario
{
name = "node_fun";

warmup = 30;
duration = 90;
cooldown = 30;

default
{
setheader
{
name = "Connection";
value = "keep-alive";
}
setheader
{
name = "Host";
value = server();
}
version = HTTP11;
statuscode = 200;
close = ka;
}

transaction
{
id = "foo";
weight = 1000;
request
{
url = "/node/logging/hello.js";
}
}
transaction
{
id = "bar";
weight = 2000;
request
{
url = "/node/helloworld/hello.js";
}
}
transaction
{
id = "baz";
weight = 2000;
request
{
url = "/node/defaultdocument/";
}
}
transaction
{
id = "bat";
weight = 2000;
request
{
url = "/node/configuration/hello.js";
}
}
}

settings.ubr

I just copied in the one from samples and uncommented out and changed (and tweaked during testing) these lines:

server         = "hexpower7";
clients = 1;
virtualclients = 8;

Now, run the Test

Next, I ran wcat.bat as an Administrator...you can see all the little node.exe's firing up. I've got a

(Remember they are running as SYSTEM because I was unable to figure out the right permissions. That's my bad, no one else's. I'll figure it out one day.)

Lots of little node processes

Here's the WCAT tool's console output...I'm able to consistently do 10,000 hello worlds a second and ended up with just under a million normal requests and responses in 90 seconds. That's a lot of hello worlds.

Remember Hanselman's Rule of Scale.

"If you do nothing, you can scale infinitely." - Me

Of course, this is all local on a fast machine. This is just hello world (with some logging) so it's not testing node much, nor IIS much, but rather the collaboration between the whole system, IIS, iisnode, and node itself.

Aside: an ASP.NET IHttpHandler doing the exact same thing on this same machine gets 22,500 requests a second, so node and iisnode has some room to improve, which is great.

Here's the node/iisnode results:

Pushing a million transactions in 90 seconds

There's a lot of things I could configure on both sites, number of clients, virtual clients, as well as iisnode-specific settings (which are, nicely enough, managed in a web.config:

<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="hello.js" verb="*" modules="iisnode" />
</handlers>
<iisnode
nodeProcessCommandLine="%systemdrive%\node\node.exe"
maxProcessCountPerApplication="4"
maxConcurrentRequestsPerProcess="1024"
maxPendingRequestsPerApplication="1024"
maxNamedPipeConnectionRetry="3"
namedPipeConnectionRetryDelay="2000"
asyncCompletionThreadCount="4"
initialRequestBufferSize="4096"
maxRequestBufferSize="65536"
uncFileChangesPollingInterval="5000"
gracefulShutdownTimeout="60000"
loggingEnabled="true"
logDirectoryNameSuffix="logs"
maxLogFileSizeInKB="128"
appendToExistingLog="false"
/>
</system.webServer>
</configuration>

This is pretty cool stuff. I like that the team I work with is excited to make things work well on IIS and I'm stoked that I can mess around with node now without firing up VMs. I'll report back as I learn more!

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Page 1 of 1 in the nodejs category

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.