What Are Good Uses for Node.js?

Not All Uses Are Good Uses for Node.js
Node.js is a server-side JavaScript environment. It uses an asynchronous event-driven model and is designed for writing scalable internet applications, notably web servers. Thus, Node.js gets excellent performance based on the architectures of many Internet applications. Programs are written in JavaScript, using event-driven, asynchronous I/O to minimize overhead and maximize scalability. Node.js is being hailed as “the new Ruby on Rails” by some in the developer community. But it’s not a magic bullet, nor is it appropriate for all programming scenarios.

Why another server side technology?
JavaScript traditionally ran in the browser. Recently there has been considerable interest in bringing it to the server side thanks to the CommonJS project. Other server-side JavaScript environments include Jaxer and Narwhal. Node.js is a bit different from these solutions. It is event-based rather than thread based. Web servers serving PHP and other CGI scripts, like Apache, are thread based. They spawn a system thread for every incoming request. The thread based model does not scale well with many long-lived connections you would need in order to serve real-time applications like Friendfeed or Google Wave.
Good Uses For Node.js
Node.js, uses an event loop instead of threads. It is able to scale to millions of concurrent connections. Node.js takes advantage of the fact that servers spend most of their time waiting for I/O operations. Reading a file from a hard drive, accessing an external web service or waiting for a file to finish being uploaded, because these operations are much slower than in memory operations. Every I/O operation in Node.js is asynchronous. The server continues to process incoming requests while the I/O operation is taking place. JavaScript is well suited to event-based programming because it has anonymous functions and closures which make defining inline callbacks a cinch, and JavaScript developers already know how to program in this way. This event-based model makes Node.js very fast, and makes scaling real-time applications very easy.
Most of the time OS threads wait till some I/O operation finish:
var result = query(“select * from users”);
for(user in result){ <- In this case the OS thread just sits and waits the I/O operation returns to resume the flow.
//You get the idea
}
Every OS thread takes some memory. Regular servers can’t handle many connections without penalizing the system performance.
node.js characteristics:
- Implemented on top of the V8 js engine (Chromium and Google Chrome engine).
- Programs are written in plain old javascript, we use the same language for client and server (Die Ruby Die!)
- Does I/O better:
query(“select * from users”, function(data, status){
//Do something really cool with users
}); - Files I/O and db queries are non-blocking
- Great performance even handling a big number of users
- It gets better every time google improves V8
- It has his own package manager called npm (node package manager)

The Goal of Node.js
Its goal is to offer an easy and safe way to build high performance and scalable network applications in JavaScript. Those goals are achieved thanks it’s architecture.
Single Threaded
Node uses a single thread to run instead of spawning a thread per request. This approach results in avoiding CPU context switching and massive execution stacks in memory. This is also the method used by nginx and other servers developed to counter the C10K problem.
Event Loop
Written in C++ using the Marc Lehman’s libev library, the event loop use epoll or kqueue for scalable event notification mechanism.
Non blocking I/O
Node avoids CPU time loss by waiting for an input or an output response (database, file system, web service, …) thanks to the full-featured asynchronous I/O provided by Marc Lehmann’s libeio library.
Node has a built-in support for most important protocols like TCP, DNS, and HTTP. The design goal of a Node application is that any function performing an I/O must use a callback. That’s why there are no blocking methods provided in Node’s API. The HTTP implementation offered by Node is complete and natively supports chunked request and response and hanging request for comet applications. The Node’s footprint for each http stream is only 36 bytes (source).
Alternatives
- Ruby Event Machine
- Python Twisted
Event driven programming analogy
The Doctor’s Office Reception Line Analogy
If we relate event-driven programming to standing in the line at a doctor’s office there are forms to fill out with insurance info, privacy releases, etc. It’s not just a question of walking in and getting into the doctor.
A Traditional Model
In a traditional thread-based system, when you get to the receptionist you stand at the counter for as long as it takes you to complete your transaction. If you have to fill out 3 forms, you would do so right there at the counter while the receptionist just sits there waiting for you. You are blocking her or him from servicing any other customers.
The only real way to scale a thread-based system is to add more receptionists. This, however, has financial implications in that you have to pay more people and physical implications in that you have to make the room for the additional receptionist windows.
Events To The Rescue
Here’s what waiting in line looks like in an event-based system. When you get to the window and find out you have to complete additional forms, the receptionist gives you the forms, a clipboard and a pen and tells you to come back when the forms are complete. You sit down and the receptionist helps the next person in line. Your filling out the form does not impede the process. When you are done with your forms, you get back in line and wait to speak with the receptionist again. If you have done something incorrectly or need to fill out another form, he or she will give you the new form or tell you the correction and you’ll repeat the process of going off, doing your work, and then waiting in line again.
This system is already highly scalable (and is in fact used in most doctor’s offices I visit). If the waiting line starts getting too l
ong, you can certainly add an additional receptionist, but you don’t need to do so at quite the rate of a thread-based system.
How Node.js Works
The “traditional” mode of web servers has always been one of the thread-based model. You launch Apache or any other web server and it starts receiving connections. When it receives a connection, it holds that connection open until it has performed the request for the page or whatever other transaction was sent. If it make take a few microseconds to retrieve a page from disk or write results to a database, the web server is blocking on that input/output operation. (This is referred to as “blocking I/O“.) To scale this type of web server, you need to launch additional copies of the server (referred to as “thread- based” because each copy typically requires another operating system thread).
In contrast, Node.js uses an event-driven model where the web server accepts the request, spins it off to be handled, and then goes on to service the next web request. When the original request is completed, it gets back in the processing queue and when it reaches the front of the queue the results are sent back (or whatever the next action is). This model is highly efficient and scalable because the web server is basically always accepting requests because it’s not waiting for any read or write operations. (This is referred to as “non-blocking I/O” or “event-driven I/O“.) To put it a bit more concretely, consider this process:
You use your web browser to make a request for “/about.html” on a Node.js web server. The Node server accepts your request and calls a function to retrieve that file from disk. While the Node server is waiting for the file to be retrieved, it services the next web request. When the file is retrieved, there is a callback function that is inserted in the Node servers queue. The Node server executes that function which in this case would render the “/about.html” page and send it back to your web browser.
Now, sure, in this case, it may only take microseconds for the server to retrieve the file, but.. microseconds matter!
Particularly when you are talking about highly-scalable web servers! This is what makes Node.js different and of such interest right now. Add in the fact that it also uses the very common language of JavaScript, and it is a very easy way for developers to create very fast and very scalable servers.
What makes Node different?
The common wisdom among many developers is that there is no single right language or framework that should and must be used for all web apps. But based on what we heard from these startups, Node is increasingly being seen as a “best solution” for a certain type of application. According to Tom Hughes-Croucher, a recent Joyent hire who is writing the first O’Reilly book on Node, “Node has popularized event-driven programming.” With event-driven programming, Hughes-Croucher explains, “The actual amount of resources you use is much smaller, and you can get a lot more out of fewer servers.”
Node is all about making event-driven, low-latency, concurrent apps. Erlang, the language that powers Facebook’s chat server, uses the same model. Tornado, a concurrent server for Python that powers FriendFeed, was an attempt at this, too. But Node has one advantage over technologies like Erlang and Tornado: “None of that was too accessible,” says Hughes-Croucher. “Node takes a language people know very well — Javascript — and makes it available to do server programming, as well.” In traditional languages and frameworks, the communication inside the app between the web server and the database is the most time-intensive part of the transaction. Node makes a much smaller footprint on your web server. It allocates web server resources on an as-needed basis, not pre- allocating a large chunk of resources for each user. For example, Apache might assign 8MB to a user, while Node assigns 8KB.
“The way that Node is more efficient on servers is by not allocating resources to things while it waits,” says Hughes-Croucher. “Say you have to talk to the database, and that’s going to take 50ms to respond. Instead of assigning all of the processing resources for that 50ms wait, it just uses a placeholder. When the database responds, then it allocates the resources needed to process. That means it’s totally possible to do a lot more requests at once, because you only allocate the server resources when you need to use them, not while you are waiting on databases.”
hands on code: hello world!
<?php
//helloworld.php
echo “hello”;
sleep(2);
echo “world!”;
?>
//helloworld.js
setTimeout(function(){
console.log(“world!”);
}, 2000);
console.log(“hello”);
There is no wasted time on the node program, the thread is idle not waiting
hands on code: http server
var http = require(“http”) ;
var server = http.createServer(function(req, res){
res.writeHead(200, {“content-type”:”text/plain”});
res.end(“Hello World!n”);
}).listen(8000);
Headers of the request are:
HTTP/1.1 200 OK
content-type: text/plain
Connection: keep-alive
Transfer-Encoding: chunked
hands on code: not only http
var net = require(“net”) ;
net.createServer(function(socket){
socket.on(“data”, function(data){
socket.write(data);
});
}).listen(8000);
hands on code: telnet chat
var net = require(“net”);
var clients = [];
net.createServer(function(socket){
clients.push(socket);
socket.on(“data”, function(data){
for(var i = 0; i < clients.length; i++){
if(clients[i] == socket) continue;
clients[i].write(data);
}
});
socket.on(“end”, function(){
var index = clients.indexOf(socket);
clients.splice(index, 1);
});
}).listen(8000);
hands on code: Async I/O
var fs = require(“fs”)
, sys = require(“sys”);;
fs.readFile(“/home/cherta/workspace/samples/foo.txt”, function(err, data){
if(err) throw err;
sys.puts(data)
});
console.log(“Antes de foo?”);
It’s a set of tools and libraries living on top of the V8.
What is not node.js?
A super framework that would change your life. Assuming that your life will change for a crappy piece of software
Working on top of node
There are killer frameworks that will make your life easier using node.
- Express web framework
- Socket IO
Express
- Web framework working on top of node.js
- High Performance
- Template engines support (jade, ejs)
- CSS engines support (sass, less, stylus)
- Partials support var app = express.createServer();
app.get(‘/’, function(req, res){
res.send(‘Hello World’);
});
app.listen(3000);
Socket I/O
Socket.IO is a Node.JS project that makes WebSockets and realtime possible in all browsers. It also enhances WebSockets by providing built-in multiplexing, ho
rizontal scalability, automatic JSON encoding/decoding, and more.
A Simple Static File Server
Any HTTP server must be able to send static files such as HTML files, images and other files. The following code does just that:
var sys = require(“sys”),
http = require(“http”),
url = require(“url”),
path = require(“path”),
fs = require(“fs”);
http.createServer(function(request, response) {
var uri = url.parse(request.url).pathname;
var filename = path.join(process.cwd(), uri);
path.exists(filename, function(exists) {
if(!exists) {
response.sendHeader(404, {“Content-Type”: “text/plain”});
response.write(“404 Not Foundn”);
response.close();
return;
}
Any HTTP server must be able to send static files such as HTML files, images and other files. The following code
does just that:
fs.readFile(filename, “binary”, function(err, file) {
if(err) {
response.sendHeader(500, {“Content-Type”: “text/plain”});
response.write(err + “n”);
response.close();
return;
}
response.sendHeader(200);
response.write(file, “binary”);
response.close();
});
});
}).listen(8080);
sys.puts(“Server running at http://localhost:8080/”);
Start by requiring all of the modules needed in the code. This includes sys, http, url, path, and fs or filesystem modules. Next, create an HTTP server. Use the url module to parse the incoming URL of the request and find the pathname of the file being accessed. Find the actual filename on the server’s hard drive by using path.join, which join process.cwd(), or the current working directory, with the path to the file being requested. Next, check if the file exists, which is an asynchronous operation and thus requires a callback.
If the file does not exist, a 404 Not Found message is sent to the user and the function returns. Otherwise, we read the file using the fs module using the “binary” encoding, and send the file to the user. If there is an error reading the file, we present the error message to the user, and close the connection. Because all of this is asynchronous, the server is able to serve other requests while reading the file from the disk no matter how large it is.
If you run this example, and navigate to http://localhost:8080/path/to/file, that file will be shown in your browser.
