Drinking the Node.js Kool-Aid
Published June 12th, 2010
**The Past and Present **
I’ve written dozens of event loops for network services, in C, C++, Python, Perl, Java, Lua, Go and probably other languages at this point. They all make me reinvent handling of events, none of them are perfect, some are faster than others, but in the end, it is a waste of my time to rewrite them.
My recent favorites has been a combination of C for the low level event loop, and higher level Lua to provide scripting of event handlers; This is what the Reconnoiter Monitoring system, the Cloudkick Agent and some proposals for Apache HTTP Server 3.0, are all built on. It generally gives you a good combination of performance with the ability to bind down to EPoll or KQueue, and the light weightiness of Lua means your processes don’t get bogged down on the memory side. But as Brian Akins was musing this week on dev@httpd, sometimes it just is not enough. In addition, I have found that most people don’t know Lua all that well, and you end up stumbling on bad practices when its exposed to a wider audience — the tooling for Lua is still limited, although I did find LuaLint this week which relieved some pain.
At the same time at Cloudkick, most of our infrastructure is build around Twisted Python Application services, communicating over combination of AMQP and Apache Thrift. Twisted Python’s name is well deserved, multi-layer callbacks can be difficult to wrap your head around, but after coding in it daily for almost a year, we can crank out mostly working code with minimal bugs — so there is some good behind it, and Inline deferreds generally make it easier to understand, but again the tooling is limited when it comes to debugging Twisted. In addition, we are always fighting with the Standard Library and common Python modules, because of Twisted’s model, you either need to do everything the ’twisted way’, or you end up sending it off to another thread anyways.
For these reasons, I have been on the lookout for something better.
Because you are always fighting the JVM and existing Java code to provide features inside the environment, you end up needing to write Java code too. In addition, almost all your JVM interfaces are blocking, meaning you are back to threading to get anywhere anyways.
**Bring on Node.js **
Node.js however doesn’t build on the JVM. It builds from a clean room environment on top of Google’s v8 engine. I played with v8 back when it was first released, cranking out an unmaintained mod_v8. It was fast back then, and has only gotten better. The best thing is its embedding API — Mozilla’s Spidermonkey has been around for ages, but it was always painful to embed and depend on it.
The main things Node has going for it:
- Everything is Async: Because the base environment has been built essentially from scratch, everything is asynchronous. This means there is no ‘defer to thread’ like in Twisted Python; You just can’t make blocking code.
- First Class Sockets and HTTP: The example Hello World is over HTTP. Node keeps you focused on on dealing with the data, rather than spending all your time dealing with the sockets or protocols.
Not a Webapp — an Application Server
Lots of people seem to be excited about building replacement’s for their Rails Website in Node, but I am not. Front end web applications aren’t that interesting to me. You take a template, fill it with variables from various sources, and send it down to the client. PHP, Django, Drupal, Rails, even Clearsilver, along with millions of other frameworks have had this figured out for a long time. They all have special features and such, but they are mostly irrelevant to me — find something your developers will have high productivity in, and let em loose.
Node is exciting because it provides a framework for producing reliable backend services, with an easily built REST-style API, that makes accessing it from anywhere else trivial. It lets you just write clean, async style code for possibly long running processes, in a garbage collected beautiful environment.
The backend engineers all too often reinvent everything every few years, with AMQP becoming more popular; And just as quickly it seems to be falling out of popularity. The tooling on backend services seems to always lag behind, Java has giant complicated things you can use, but they aren’t the right fit for most projects. Apache Thrift presented at least a common communications platform for services which is a good start, and hopefully Apache Avro will make them even easier to use.
Backend services lack a Rails. They lack a Django. They lack a JQuery or Dojo. They lack a revolution in how things are structured and built. Maybe it was SOA, or REST, or a million other terrible acronyms, but it all got mired in stupid marketing. Node.js seems to have the possibility to change how I build application servers, and for that reason I am very excited for Node’s future.
**What I’ve been hacking on! **
Full drinking the Kool-Aid disclaimer: Earlier today, my first patch to Node.js was merged. It provided UDP & dgram unix daemon socket support. I don’t think it makes me a biased Node.js zealot yet, I just contributed it because it seemed useful for my own projects, and I wrote it in only a few hours.
I wrote the UDP patch to support my unpublicized Dislocate project. It is basically seeking to unify service discovery, load balancing and administration across multiple data centers with varying latency — something I think is required to build true auto-scalling solutions. It is replacing in a sense part of DNS, part of Load Balancers, and part of configuration management. I am hoping to get something like a first beta release out this June of Dislocate, and will write up more about it at that time.
Written by Paul Querna, CTO @ ScaleFT. @pquerna