The Functional Web                                              Node.js: Using JavaScript                                 ...
Node.js: Using JavaScriptthe select() and poll() Unix sys-          applications in certain programming        have releas...
The Functional Web     var sys = require(“sys”),         http = require(“http”),         url = require(“url”),            ...
Node.js: Using JavaScript                                                 var sys = require(“sys”),                       ...
Upcoming SlideShare
Loading in …5

Node.js: Using JavaScript to Build High-Performance Network Programs


Published on

Published in: Technology
1 Like
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Node.js: Using JavaScript to Build High-Performance Network Programs

  1. 1. The Functional Web Node.js: Using JavaScript to Build High-Performance Network Programs Stefan Tilkov • innoQ Steve Vinoski • Verivue N ode.js — also called Node — is a server- stand, implement, and maintain but also enable side JavaScript environment (see http:// faster, more efficient execution. It’s based on Google’s runtime For applications such as Web servers perform- implementation — the aptly named “V8” engine. ing significant amounts of I/O, multiple threads V8 and Node are mostly implemented in C and enable applications to better use available pro- C++, focusing on performance and low memory cessors. Running multiple concurrent threads on consumption. But, whereas V8 supports mainly a modern multicore system is straight forward, JavaScript in the browser (most notably, Google with each core simultaneously executing a dif- Chrome), Node aims to support long-running ferent thread with true parallelism. On single- server processes. core systems, the single processor executes one Unlike in most other modern environments, thread, switches to another and executes it, and a Node process doesn’t rely on multithreading so on. For example, the processor switches its to support concurrent execution of business execution context to another thread when the logic; it’s based on an asynchronous I/O event- current thread performs an I/O operation, such ing model. Think of the Node server process as a as writing to a TCP socket. The switch occurs single-threaded daemon that embeds the Java- because completing that operation can take Script engine to support customization. This is many processor cycles. Rather than wasting different from most eventing systems for other cycles waiting for the socket operation to finish, programming languages, which come in the the processor sets the I/O operation in motion form of libraries: Node supports the eventing and executes another thread, thus keeping itself model at the language level. busy doing useful work. When the I/O operation JavaScript is an excellent fit for this approach ends, the processor again considers the original because it supports event callbacks. For exam- thread to be ready to execute because it’s no lon- ple, when a browser completely loads a docu- ger blocked while waiting for I/O. ment, a user clicks a button, or an Ajax request Even though many developers have suc- is fulfilled, an event triggers a callback. Java- cessfully used multithreading in production Script’s functional nature makes it extremely applications, most agree that multithreaded easy to create anonymous function objects that programming is anything but easy. It’s fraught you can register as event handlers. with problems that can be difficult to isolate and correct, such as deadlock and failure to protect Multithreading versus Events resources shared among threads. Developers Application developers who deal with multiple also lose some degree of control when draw- I/O sources, such as networked servers handling ing on multithreading because the OS typically multiple client connections, have long employed decides which thread executes and for how long. multithreaded programming techniques. Such Event-driven programming offers a more techniques became popular because they let efficient, scalable alternative that provides devel- developers divide their applications into con- opers much more control over switching between current cooperating activities. This promised to application activities. In this model, the applica- not only make program logic easier to under- tion relies on event notification facilities such as80 Published by the IEEE Computer Society 1089-7801/10/$26.00 © 2010 IEEE IEEE INTERNET COMPUTING
  2. 2. Node.js: Using JavaScriptthe select() and poll() Unix sys- applications in certain programming have released high-performancetem calls, the Linux epoll service, languages to deal with events and JavaScript runtime implementationsand the kqueue and kevent calls asynchronous I/O. This is because that are extremely fast and scalable.available in BSD Unix variants such different events require differentas OS X. Applications register interest actions in different contexts. Pro- The Nodein certain events, such as data being grams typically employ callback Programming Modelready to read on a particular socket. functions to deal with events. In Node’s I/O approach is strict: asyn-When the event occurs, the notifica- languages that lack anonymous chronous interactions aren’t thetion system notifies the application so functions and closures, such as C, exception; they’re the rule. Everythat it can handle the event. developers must write individual I/O operation is handled by means Asynchronous I/O is important for functions specifically for each event of higher-order functions — thatevent-driven programming because and event context. Ensuring that is, functions taking functions asit prevents the application from get- these functions all have access to a parameter — that specify what toting blocked while waiting in an I/O the data and context information do when there’s something to do. Inoperation. For example, if the appli- they require when they’re called to only rare circumstances have Node’scation writes to a socket and fills the handle an event can be incredibly developers added a convenience func-socket’s underlying buffer, ordinar- perplexing. Many such applications tion that works synchronously — forily, the socket blocks the application’s end up being little more than impen- example, for removing or renamingwrites until buffer space becomes etrable, unmaintainable tangles of files. But, generally, when opera-available, thus preventing the appli- spaghetti code and global variables. tions that might require network orcation from doing any other useful file I/O are invoked, control is imme-work. But, if the socket is nonblock- Not Your Father’s JavaScript diately returned to the caller. Whening, it instead returns an indication Whatever you might think about something interesting happens — forto the application that further writ- JavaScript as a programming lan- example, if data becomes availableing isn’t currently possible, thereby guage, there’s little to no doubt it for reading from a network socket,informing the application that it has become a central element of an output stream is ready for writing,should try again later. Assuming the any modern HTML-based applica- or an error occurs — the appropriateapplication has registered interest tion. Server-side JavaScript is a logi- callback function is called.with the event notification system in cal next step, enabling the use of a Figure 1 is a simple example ofthat socket, it can go do something single programming language for all implementing an HTTP Web serverelse, knowing that it will receive an aspects of a Web-based distributed that serves static files from disk.event when the socket’s write buffer application. This idea isn’t new — for Even to non-Web developers, Java-has available space. example, the Rhino JavaScript exe- Script’s syntax should be fairly obvi- Like multithreaded program- cution environment has been avail- ous for those with prior exposure toming, event-driven programming able for a long time. Still, server-side any C-like language. One of the morewith asynchronous I/O can be JavaScript isn’t yet a mainstream specific topics is the function(...)problematic. One problem is that approach and has only recently syntax. This creates an unnamednot all interprocess-communication gained massive popularity. function: JavaScript is a functionalapproaches can be tied into the event We believe that a number of language and, as such, supportsnotification facilities we mentioned factors have led to this effect. The higher-order functions. A developerearlier. For example, on most OSs, advent of the set of technologies col- writing or looking at a Node programfor two applications to communicate lectively labeled “HTML 5” reduces will see these everywhere.through shared memory, shared- the appeal of alternative client-side The program’s main flow is deter-memory segments provide no han- platforms, enforcing the need to get mined by the functions that aredles or file descriptors enabling the to know and exploit JavaScript to explicitly called. These functionsapplication to register for events. For create rich user interfaces. NoSQL- never block on anything I/O-related,such cases, developers must resort type databases such as CouchDB but rather register appropriate han-to alternatives such as writing to and Riak use JavaScript to define dler callbacks. If you’ve seen a simi-a pipe or some other event-capable data views and filter criteria. Other lar concept in eventing libraries formechanism together with writing to dynamic languages, such as Ruby other programming languages, youshared memory. and Python, have become acceptable might wonder where the explicit Another significant problem is choices for server-side development. blocking call to invoke the event loopthe sheer complexity of writing Finally, both Mozilla and Google hides. The event loop concept is soNOVEMBER/DECEMBER 2010 81
  3. 3. The Functional Web var sys = require(“sys”), http = require(“http”), url = require(“url”), layer is ready to hand a number of path = require(“path”), bytes to the application, when the fs = require(“fs”); file has been read completely, or when some kind of error occurs. If http.createServer(function(request, response) { data is available, it’s written to the var uri = url.parse(request.url).pathname; HTTP output stream. Node’s sophis- var filename = path.join(process.cwd(), uri); ticated HTTP library supports HTTP path.exists(filename, function(exists) { 1.1’s chunked transfer encoding. if(exists) { Again, both reading from the file fs.readFile(filename, function(err, data) { and writing to the HTTP stream hap- response.writeHead(200); pen asynchronously. response.end(data); The example in Figure 2 shows }); how easily developers can build a } else { high-performance, asynchronous, response.writeHead(404); event-driven network server with response.end(); modest resource requirements. The } main reason is that JavaScript, owing }); to its functional nature, supports }).listen(8080); event callbacks. In fact, this pattern sys.log(“Server running at http://localhost:8080/”); is well known to any client-side Java- Script developer. In addition, makingFigure 1. A simple HTTP file server. Events trigger anonymous functions that asynchronous I/O the default forcesexecute input or output operations. Incoming requests trigger the server to developers to adopt the asynchro-parse the target URI, look for a local file matching the URI path, and, if found, nous model from the start. This isread the file contents and write them along with appropriate HTTP headers one of the main differences betweenas a response to the client. Node and using asynchronous I/O in other programming environments, in which it’s only one of many optionscore to Node’s behavior that it’s hid- threaded, yet can serve many clients and is often considered too advanced.den in the implementation; the main concurrently. This seems a contra-program’s purpose is simply to set diction, but recall that there’s an Running Multiple Processesup appropriate handlers. The http. implicit main loop around the code, In hardware environments in whichcreateServer function, which is a and what’s actually happening in more than one physical CPU or corewrapper around a low-level efficient that loop is just a number of regis- is available, parallel execution isn’tHTTP protocol implementation, is tration calls. No actual I/O, let alone an illusion but a reality. Althoughpassed a function as the only argu- business-logic processing, happens the OS can efficiently schedule ament. This function is invoked when- in the loop body. I/O-related events Node process with its asynchronousever data for a new request is ready trigger the actual processing, such I/O interactions in parallel withto be read. In another environment, as a connection being made or bytes other processes running on the sys-a naïve implementation might ruin being sent or received from a socket, tem, Node still runs in a single pro-the effect of eventing by synchro- file, or external system. cess and thus never executes its corenously reading a file and sending it Figure 2 is a slightly more com- business logic in parallel. The com-back. Node offers no opportunity to plex variant of the simplistic HTTP mon solution to this problem in theread a file synchronously — the only server, but it does a lot more. Again, Node world is to run multiple pro-option is to register another func- it parses the URI from an HTTP cess instances.tion via readFile that gets invoked request and maps the URI’s path To support this, the multi-nodewhenever data can be read. component to a filename on the library (see server. But this time, the file is read zyp/multi-node) leverages the OS’sConcurrent Programming in smaller chunks rather than all at capability of sharing socketsA node server process, usu- once. In certain situations, the func- between processes (and is imple-ally invoked from the command tion provided for the scenario as a mented in fewer than 200 lines ofline using something like “node callback is invoked. Example situ- Node JavaScript). For example,<scriptname>,” runs single- ations include when the file system you can run HTTP servers such as82 IEEE INTERNET COMPUTING
  4. 4. Node.js: Using JavaScript var sys = require(“sys”), http = require(“http”),those in Figures 1 and 2 in paral- url = require(“url”),lel by invoking multi-node’s lis- path = require(“path”),ten() function. This starts multiple fs = require(“fs”);processes that all listen on the sameport, effectively using the OS as an http.createServer(function(request, response) {efficient load balancer. var uri = url.parse(request.url).pathname; var filename = path.join(process.cwd(), uri);A Server-Side path.exists(filename, function(exists) {JavaScript Ecosystem if(exists) {Node is one of the better-known f = fs.createReadStream(filename);frameworks and environments that f.addListener(‘open’, function() {support server-side JavaScript devel- response.writeHead(200);opment. The community has created });a whole ecosystem of libraries for, or f.addListener(‘data’, function(chunk) {compatible with, Node. Among these, response.write(chunk);tools such as node-mysql or node- setTimeout(function() {couchdb play an important role by f.resume()supporting asynchronous interaction }, 100);with relational and NoSQL data stores, });respectively. Many frameworks pro- f.addListener(‘error’, function(err) {vide a full-featured Web stack, such response.writeHead(500, {“Content-Type”:as Connect and Express, which are “text/plain”});comparable to Rack and Rails in the response.write(err + “n”);Ruby world in scope, if not (yet?) in response.end();popularity. The Node package man- });ager, npm, enables installation of f.addListener(‘close’, function() {libraries and their dependencies. response.end();Finally, many libraries available for });client-side JavaScript that were writ- } else {ten to comply with the CommonJS response.writeHead(404);module system also work with Node. response.end();An impressive list of modules avail- }able for Node is at });ry/node/wiki/modules. }).listen(8080); sys.log(“Server running at http://localhost:8080/”);G iven that, in most Web develop- ment projects, JavaScript knowl-edge is a prerequisite for advanced Figure 2. A simple streaming HTTP file server. Chunks of the file are read from disk and sent to the client using HTTP’s “chunked” transfer encoding.UI interactions, the option of usingone programming language for certain social network where he’s identi-everything becomes quite tempt- fied as Node.js’s architecture makesit easy to use a highly expressive, Steve Vinoski is a member of the technicalfunctional language for server pro- staff at Verivue. He’s a senior membergramming, without sacrificing per- of the IEEE and a member of the ACM. Our experts.formance and stepping out of the You can read Vinoski’s blog at http:// Your future.programming mainstream. and contact him at Tilkov is cofounder of innoQ, a tech- nology consultancy with offices in Ger- Selected CS articles and columns many and Switzerland. He blogs at www. are also available for free at http:// and is addicted to a 2010 83