JavaScript conquers the server

Node.js, Jaxer, EJScript, RingoJS, and AppengineJS combine the familiarity of JavaScript, low overhead, blazing speed, and unique twists

In 1996 when no one believed in Apple and AOL was voted most likely to succeed, Netscape took its shiny, new JavaScript language from the browser and stuck it in the Netscape Enterprise HTTP server. That was probably the first moment that someone tried to make JavaScript the lingua franca for back-office servers, but it wasn't the last. After Netscape dissolved into Mozilla, new stacks with JavaScript have come and gone as the true believers try again and again.

Now some 15 years later, JavaScript on the server is back in vogue. The buzz from the latest round of believers is that JavaScript is the "new Ruby," for all of the same reasons that Netscape began the trend. Using the same code for the client and the server makes life easier for everyone -- you never know when you'll need to move a routine from one to the other. I can't tell you how many times I've tried to make sure that the Java version of the SHA256 hash algorithm running on the server produced the same output as the JavaScript version running on the client.

[ Also on InfoWorld: 13 open source development projects making waves in the enterprlse. See "Open source programming tools on the rise." | Keep up on key application development insights with the Fatal Exception blog and Developer World newsletter. ]

But some things are different this time. Many of the earlier efforts were built around perfectly nice JavaScript engines like Rhino that offered perfectly acceptable performance. Now we have a number of new JavaScript engines such as Google's V8, which is much faster and uses many of the just-in-time compilation ideas that sustained Java's virtual machines over the years. Suddenly JavaScript is speedy enough that people think of using it for its velocity, not its convenience. It's entirely possible that all of the hard work on the browser engines is making JavaScript the fastest dynamic language and one of the best choices for server-side programming.

To understand the latest burst of enthusiasm, I spent some time installing a few of the more interesting JavaScript servers and building a few basic websites. The tools were all intriguing, thoroughly fun, and oozing -- the software equivalent of a fresh, clean coat of latex paint. This newness cut both ways, though, because some of the documentation was sketchy and many of the demonstrations were not much more complicated than spitting out "hello world."

I enjoyed the challenge and stimulation of rethinking everything I know about the server, but I still found myself hesitant to push these new ideas too far or too fast. These servers are fresh from the lab and made for experimenting, not building an application for Grandma to check the interest on her CDs. The ideal project for a corporation might be a temporary website for a one- or two-day event that would come and go in a flash. For now, enjoy creating something new and fun with them, not betting your business.

JavaScript servers: Node.js

The hottest star is undeniably Node.js, a simple package that is attracting the kind of attention that leads people to roll out the term "fanboy." Blogs such as How to Node are filled with hints and suggestions as people try to figure out just how far they can push the tool. There's already been a conference devoted to the project, and people are using the word "node" as a verb that means to write Node.js code. Will the language still be around next winter for us to make puns about "bad code in the node"? I'm sure the ideas will still be here because they're powerful, but the names may morph into something else because there's plenty of reinvention in this space.

The most powerful idea is that Node.js is light, whereas alternatives such as Java are heavier. The secret of the tool's success seems to lie in one factoid often repeated by Node.js lovers: a Java server uses 2MB of RAM just to create a thread. As the standard Java Servlet container creates one thread for each request, it's clear that a fairly hefty server with, say, 8GB of free RAM can handle only 8,000 people. Of course the threads often use more memory, which further cuts into the overhead and positions 8,000 as an upper limit.

Threads were supposed to be lightweight ways for a processor to juggle the workload, and they were certainly successful back when people were satisfied with handling several thousand simultaneous users. But when people started counting up the costs of the overhead for bigger and bigger websites, some started wondering if there was a better way.

Node.js is one good solution. It uses only one thread for your server and everything runs within it. When the requests come flying in, Node.js takes them one at a time and hands them to the single function that was specified when the server is invoked. If you thought that a Java Server Page, a Java Servlet, or a PHP file was a lightweight way of building a website, you'll be impressed with the efficiency of this:

function website(req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('hello world\n'); }

What? If you're going to point out that a JSP or PHP file may be as simple as the words "hello world," stop right there. You have to think beneath the surface and remember everything that the Java Servlet container or PHP server does for you. You may just write "hello world" in a JSP, but Java will burn 2MB of RAM creating a thread that supports the code that will eventually output the thread "hello world." The JSP might seem simple, but it's not.

Node.js does very little except grab the incoming request, call the function website, and marshal the results out the door. This single-mindedness lets it juggle all of the requests hammering at the port and dispatch them quickly.

I've seen standard-issue desktop machines easily handle thousands of requests more or less simultaneously. The data goes in and out like lightning because everything is handled in RAM and probably in the cache. Simple websites are surprisingly efficient.

But it's important to recognize that some of this lightning speed comes from leaving out other features. Running everything in one thread means everything can back up if that thread gets overloaded. All of the work that Java spends on putting clean, fresh sheets on the bed really pays off if one thread takes a long time to finish.

To make this happen, I created a simple server that takes a value "n" and adds up all of the numbers between 1 and n. This, by the way, is a purely CPU-bound operation that should use only two registers. It can't get hung up by waiting for RAM or the file system. The server was just as fast as before. I had to feed my underpowered desktop (1.83GHz Intel Core Duo) numbers like n=90000000 before it seemed to pause at all. That's a 9 with seven 0s after it. The answer had 16 digits in it.

When I fed fat numbers to the server, I found that all of the other requests would get in line behind it. When the workload is short, Node.js seems to be multitasking because it gets done with everything so quickly. But if you find an item that weighs down the server, you can lock up everything in a queue behind it.

Fear not. If this happens, Node.js lovers will blame you, not the machine. Your job as a programmer is to anticipate any delays, such as a request for a distant Web service. Then you break your code into two functions, just as AJAX programmers often do on the client. When the data is returned, Node.js will invoke the callback function. In the meantime, it will handle other requests.

In the right hands connected to a right-thinking mind, the results can be staggeringly efficient. When the programmer spends a few minutes and separates the work done before and after a delay, there's no need for the machine to tie up RAM to hold the state in the thread just so it will be ready when the data finally shows up from the database or the distant server or even the file system. It was undeniably easier for the programmer to let the computer keep all of the state, but it's much more efficient this way. Just as businesses try desperately to avoid tying up capital in inventory, a programmer's job is to think like a factory boss, treat RAM as capital, and avoid consuming any of it.

This mind-set may seem like a burden to programmers who are used to letting the compilers think about such things, but JavaScript programmers are accustomed to working with callback functions because that's how the browser's sandbox is configured. This kind of segmentation is second nature to them, and that's why they're so in love.

I think Node.js will quickly grow beyond doing simple experiments and begin to handle semiserious but lightweight tasks such as online polls and simple message passing between users. If the server workload is simple and short-lived, Node.js is a good solution. The tools are solid, at least as experimental, bleeding-edge code goes, and I expect that skilled JavaScript programmers will be able to write simple chains of callbacks that do some amazing things with low-rent iron. Will bigger responsibilities follow? I suppose that's possible, but for now this is enough for everyone to digest.

JavaScript servers: Jaxer

Another, completely different option for the JavaScript lover is Jaxer, a nice tool from Aptana, the folks who make a great, Eclipse-based IDE for Ruby and PHP. Aptana's tool for server-side Java is very different from Node.js because it's aimed more at making life easier for the programmer rather than the server. Jaxer handles all the complexity of message passing behind the scenes, so writing server-side code is like writing client code.

Writing a server-side script for Jaxer is just like writing one for a Web page. The difference is that you sneak the attribute runat='server' into the script tag. That's it. Everything else is akin to building a JavaScript-enabled Web page. Whenever you call a function with the special runat attribute, it will be executed on the server, not in the browser. Jaxer handles the chores of bundling the parameters into an AJAX call. One little attribute controls where the code runs, and Jaxer handles all of the message passing and invocations.

The freedom can be a bit unnerving for old hands at JavaScript programming who've spent years thinking they were programming only the client. Now you can write to the database or access distant files by merely inserting the runat attribute.

I found it pretty easy to build Web pages using the technique. Anyone who is new to AJAX will discover it's much more convenient to let Jaxer handle all of the background work of bundling and unbundling the data. It's all mostly automatic and even simpler to use than some of the AJAX libraries such as jQuery.

It's not clear how much support Jaxer is enjoying these days. The server used to be bundled with Aptana's other offerings, but now it's left alone in a corner. My guess is that many people don't need that much help handling AJAX calls now that libraries like jQuery simplify the process.

The ideal job for Jaxer will be one where most of the work is done on the client but some crucial part must run on the server. It's very easy to make code run on the server, but it's not so easy to write complex server-side code. There are plenty of jobs like this, and the people coding these jobs are the ones that Aptana is targeting when it says you can write an entire Web application in one file.

JavaScript servers: EJScript
Although the idea of using JavaScript on the server sounds simple, there are a surprisingly diverse number of ways to approach it. EJScript is quite different from both Jaxer and Node.js but very similar in structure to classic server designs like Ruby on Rails and Struts. It's built using the pure Model-View-Controller paradigm, so it will be quite familiar to anyone who's created websites using the popular Ruby or Java frameworks.

The basic tool is a command line that can either execute JavaScript or create a Web server. If you want to write your server scripts in JavaScript, the basic shell will do so. If you want to create websites, the tool will build out websites using standard scaffolding for all of the create, update, and delete (CRUD) operations on the data.

The entire process is similar to coding in Java and the various server frameworks in part because EJScript includes a way to define classes and subclasses. This object-oriented structure is a great enhancement for JavaScript if you ask me, but it's going to be different for anyone who's learned JavaScript in the browser. Although most JavaScript programmers know plenty about monkeying around with the prototypes, they may not be as familiar with how Java and other object-oriented languages build out type hierarchies.

EJScript borrows from Ruby on Rails because many parts of the scaffolding are defined by "convention not configuration." The directories are in standard locations, and often the easiest solution is to create a file with the right name. To further differentiate from JavaScript, there's no need for a trailing semicolon if you put the statements on separate lines. The Python and CoffeeScript model is beating out the old C and Pascal worldview.

1 2 Page
Join the discussion
Be the first to comment on this article. Our Commenting Policies