Noodling with Node.js
Been having a little play around with a new(ish) thing - Node.js. Only at a simple noddy level admittedly, but it's already one of the more interesting technologies I've come across recently.
Essentially it's an extremely scalable event-driven web server. OK, it does a few other things, but the focus is definitely on low level HTTP and TCP.
It's JavaScript based, and built on top of Google's V8 open source JavaScript engine.
Standing on the shoulders
Built by a small Danish team, V8 is a really impressive JavaScript compiler. It's cross platform, very fast, and is the VM used inside the Chrome browser. The lead engineer is Lars Bak - the technical lead on Sun's HotSpot VM, and before that, Smalltalk. So it has some pedigree.
Then there is CommonJS. This is a JavaScript library spec, concentrating on server side development. Previously server side JS has been a rather fragmented affair, with multiple implementations. CommonJS attempts to define some standards in this area. Node.js had adopted the modules and unit testing from the CommonJs project.
Node.js builds on top of these, wrapping it all with an event driven model with non-blocking I/O and handy System/HTTP modules.
What it solves
An event based server solves certain specific problems that can occur when scaling up long running I/O or requests in more traditional architectures. Simon Wilison explains it best, naturally using hamsters, bunnies, and a hyperactive squid.
In a standard web server, like JEE, I/O and calls to other services will tend to be done synchronously within a thread. Scaling is achieved by creating a new thread per connection. If you've potentially long running processes in there, then you'll block that thread, using up increasing server resources or slowing down requests. Some of this can be mitigated by using MQ to add asynchronous handling for certain things, or Java NIO for async I/O, but it's interesting to see Node.js has this approach ingrained across the board.
Threaded models drop in performance as concurrency increases. The non-blocking event model stays relatively steady. Note it's not quite this simple - you're backend still has to scale. But it does remove at least one bottleneck.
The event driven model in Node.js uses the callback pattern to say "do this bit of possibly long running stuff, then call this other method when you're done". It can then carry on with other processing or other requests immediately.
Examples
Installing Node.js means a build and compile currently, but it's a very simple deal. Though note at the time of writing it needs a Mac or Linux (or any Posix type thing) - Windows isn't supported yet. See the Node.js website for more. Running is simply a case of typing "Node <your JS file>".
Non-blocking calls
The main thing Node.js add is callbacks across the board. All I/O become asynchronous. This means calls change slightly:
The second example happens to be an anonymous function, but could be any function defined elsewhere. The key is when you call any long running process, you also set what to call when it finishes. It the meantime you move on so no time is wasted.
This will be a really familiar idiom to anyone who's done much Ajax - it's the same idea, do something async & pass in a function to call when you're done. JavaScript just happens to be really well suited to this pattern with it's first order functions and closures.
Basic web server - Hello World!
Node.js has built in libraries for handling low level HTTP, TCP and DNS along with general I/O operations. Creating a basic web server is simple:
A Twitter client
You can also create an HTTP client relatively easy. Here's one to query Twitter (a fairly canonical example, adapted and annotated)
Practical use
It doesn't look like you'd want to write an full application using Node.js - it's far too low level. And it's not exactly mature yet. But some possible uses spring to mind:
- Put it on a subdomain to have it handle Comet style long running/push requests
- Similarly, use it to handle uploads that could go on a long time
- As it contains an HTTP server & client, it could be used as a quick proxy or for routing requests
- The HTTP client is easy to use and negligible CPU/memory when not active, could be left running to poll websites for availability or running tests
- It's got a nice TCP library - makes talking across sockets a breeze. We used to have a WebSphere server talk to a backend machine over sockets - this would have been ideal for receiving and allocating those requests.
- Combine with CouchDB simply for the bizarre situation of having all your tiers running JavaScript.
Seems to be something to keep an eye on...



Comments [0]