Why node.js Matters

June 13, 2010

Since the days when I coded my first reactor [POSA2] back at MIT, I have been convinced of the conceptual simplicity of non-blocking event driven server. Aside not blocking for I/O and being able to scale well beyond polling architectures, it is harder, sometimes impossible, to make concurrent programming mistakes with an event-driven programming paradigm. However, reactor servers never took off massively, probably because event based programming of server-side applications is a more complex programming paradigm for the average programmer than a thread- or process-per-request. In in a way, we have had not enough pressure to move, yet. Things would just work, reasonable well.

But I believe we are finally at a turning point. Multi-core architectures imply the end of the free lunch. It is happening. Writing highly concurrent server-side applications that are able to scale linearly as the number of cores increases is something that we should be preparing for.

Once you believe reactor servers are the future, and somewhat the present, comes the question of programming language. When it comes to programming for the web, there are many religions and options: PHP, Ruby, Python, Java, C#, ... However, when it comes to writing web applications, there are three languages on which all web developers agree universally on: HTML, CSS and Javascript.

And this is what makes node.js exciting. node.js develops a reactor server on top of Google's V8 Javascript engine. First, it solves the free lunch problem using a language that is universally accessible to web developers. Second, it opens the door for innovation to a world of extremely high concurrency, for example, MMORPGs, and potentially to a completely different web interaction paradigm.

With motivation in mind, I set myself to learn a bit more about node.js. I chose one possible stack, node.js + express + mongodb, but there are many more to learn. What follows in the rest of this post are my raw notes, which I am posting here just in case it helps fellow developers getting up to speed in all this new cool technology.

Installation

First, we install node.js itself, and kiwi, a packaging system for node.js, using homebrew (I have dropped Macports in favor of homebrew, as it allows me to create my own installation recipes really easily).

$ brew install node
$ brew install kiwi

That installed for me:

kiwi (0.3.1)
node (0.1.98)

Once we have kiwi, we install the express framework:

$ kiwi -v install express

Finally, we install mongodb:

$ brew install mongodb

If this is your first install, automatically load on login with:
    cp /usr/local/Cellar/mongodb/1.4.3-x86_64/org.mongodb.mongod.plist ~/Library/LaunchAgents
    launchctl load -w ~/Library/LaunchAgents/org.mongodb.mongod.plist

If this is an upgrade and you already have the org.mongodb.mongod.plist loaded:
    launchctl unload -w ~/Library/LaunchAgents/org.mongodb.mongod.plist
    cp /usr/local/Cellar/mongodb/1.4.3-x86_64/org.mongodb.mongod.plist ~/Library/LaunchAgents
    launchctl load -w ~/Library/LaunchAgents/org.mongodb.mongod.plist

Or start it manually:
    mongod run --config /usr/local/Cellar/mongodb/1.4.3-x86_64/mongod.conf

And finally, the native adapter to mongodb for node.js:

$ kiwi install mongodb-native

Hello World

Fire text editor and create app.js:

var kiwi = require('kiwi')
kiwi.require('express')

get('/', function(){
  this.contentType('html')
  return '<h1>Welcome To Express</h1>'
})

run()

And back to the terminal:

$ node app.js

Point the browser to:

http://localhost:3000/

Tutorial App

I found a good blog with many node.js tutorials, including one on building a blog app example that included source code using express and mongodb.

To run the demo, first start mongodb, and then node.js (I used two terminal windows):

$ mongod run --config /usr/local/Cellar/mongodb/1.4.3-x86_64/mongod.conf
$ node app.js

And then visit http://localhost:3000/. I could not create a new blog post by visiting http://localhost:3000/blog/new, as I'd get an error:

/Users/brunofr/Projects/express-mongodb-2/app.js:39
        title: article.title,
                      ^
TypeError: Cannot read property 'title' of undefined
    at /Users/brunofr/Projects/express-mongodb-2/app.js:39:23

Looking at the code, it seems like the route blog/* is being executed before blog/new:

get('/blog/*', function(id){
  var self = this;
  articleProvider.findById(id, function(error, article) {
    self.render('blog_show.html.haml', {
      locals: {
        title: article.title,
        article:article
      }
    });
  });
});

get('/blog/new', function(){
  this.render('blog_new.html.haml', {
    locals: {
      title: 'New Post'
    }
  });
});

Reversing the order fixed the problem.

Benchmark

I found one interesting benchmark, on Express vs sinatra, which as always should be taken with a grain of salt. But the benchmark illustrates some of the properties of reactor servers that we have been talking about.


blog comments powered by Disqus