Home » Our Blog » What Are Good Uses for Node.js?
October 9, 2013

What Are Good Uses for Node.js?

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.

Good Uses for Node.JS

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)

Node.js to Twitter

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.

Node.js Local Host

Ready to create some awesome content Google will love?

Get a free Content Audit

Complete the form to download

Don’t you wish you could pay for your morning coffee with just an email address?

    Congrats on the new ebook
    Thanks for downloading it.

    Digital Firefly Marketing is excited about our collection of eBooks.

    That’s because they are conceptualized, planned and written by us drawing from our expertise and experience. That means you get information that doesn’t just sound good, but has been used to actually help our clients.

    Be sure to check out all of our eBooks and contact us if you’d like help developing your website or building your marketing strategy.

    For now, pour yourself a beverage and tuck into our user-friendly eBooks to learn how you can improve your website’s visibility.

    Visit Our Blog

    No, Thanks. I’ll Check out Later.