March 2012

Volume 27 Number 03

Azure Insider - Write Scalable, Server-side JavaScript Applications with Node.js

By Bruno Terkaly |March 2012

If you live in the Silicon Valley area, you have already heard the buzz: Node.js is being hailed as the next big thing. It’s the silver bullet that offers scale, eases development, and can be leveraged by the vast pool of client-side JavaScript developers. So, what exactly is Node.js?

Node.js is a server-side JavaScript environment that uses an asynchronous event-driven model. It is based on Google's V8 JavaScript engine plus several built-in libraries. The excitement around Node.js is that the barriers to entry are remarkably low; if you know JavaScript, you're well on your way to writing code on the server side. Real-world examples are easy to find. Numerous organizations, such as Twitter, WordPress and Facebook—just to name a few—have already embraced Node.js.

One of the biggest promises of Node.js is amazing performance for HTTP and TCP. Much of the inherent performance advantage is because Node.js is event based. It frees developers from having to worry about managing the notoriously complex world of threads and processes. Node.js excels at IO-bound operations. It specifies a callback method prior to an IO operation, allowing it to process other requests while the IO-bound operations are executing. This indeed is the wizardry of Node.js. Thread and process management is nothing short of a nightmare, accounting for a vast majority of bugs in modern software.

Still, developers should be mindful that there's always a tradeoff. In this case, it’s important to remember that Node.js doesn't excel at CPU-bound operations and should be used primarily for optimizing calls to IO operations. Also, Node.js is inherently single-threaded; this means it isn't the best fit for machines with multiple cores because its single-threaded event loop takes only a single request at a time and processes it. Having said this, for the open Web this limitation isn't that relevant: most Web-based applications are IO-bound, not CPU-bound, meaning that a client request is usually waiting on some kind of IO operation, such as reading from the database or getting data from yet another Web service call.

An indication of the increasing popularity of Node.js is the number of projects in source code available on GitHub, where Node.js is undergoing phenomenal growth. GitHub is a distributed version control system and is one of the central clearinghouses for open source projects.

The good news is that Microsoft has welcomed Node.js, specifically as it relates to cloud computing—that is, Azure. Node.js makes a lot of sense in the cloud because developers can scale up and scale down as needed to provide power during busy times and to save money when usage drops. Moreover, with a global cloud offering, software development companies can easily support users throughout the world. Microsoft offers a series of global data centers, allowing developers to host Node.js applications in the United States, Europe or Asia—wherever is most geographically convenient for the users.

One of the big challenges to supporting scalable applications is providing updates without accruing any downtime. Azure automates the upgrade process, making it easy for developers to apply updates without affecting the user experience. There is even a staging environment that can be used for testing an upgraded application before rolling it into production. What this means is that developers can focus on the Node.js application, not the underlying infrastructure used to support it. This form of cloud computing is called Platform-as-a-Service (PaaS), as opposed to Infrastructure-as-a-Service (IaaS). IaaS is less optimal than PaaS because it requires companies to manage virtual machines and deal with the details of networks, load balancers and failure recovery.

Let’s look at some simple Node.js code. Imagine you want to provide prime numbers to a Web browser from a Node.js application. Figure 1 shows the code, and I have documented the whole process here. As you can see, this is straight-up JavaScript. Take special note of the response.write() statement, which spits the list of prime numbers up to 500 back as HTML to a client browser. 

Figure 1 A Simple Node.js Application

http = require('http');
http.createServer(function (request, response) {
  request.addListener('end', function () {
      var buf = '<div style=\"color:green;\">' + '2' + 
          ' is prime.  </div>';
      for (var i = 2; i < 500; i++)
      {
          for (var j = 2; j < i; j++)
          {
              if (i % j == 0)
              {
                  var prime = 'no'
                  var tmp = '<div style=\"color:red;\">' + i +
                              ' is not prime.  It is divisible by ' + 
                              j + '</div>';
                  buf += tmp;
                  break;
              }
              else
                  var prime = 'yes';
          }
          if (prime == 'yes')
          {
              var tmp = '<div style=\"color:green;\">' + i + 
                 ' is prime.  </div>';
              buf += tmp;
          }
      }
      response.write('<html><body><p>' + buf +
          '</p></body></html>');
      response.end();
  });
}).listen(8000, 'localhost');
console.log('system waiting at http://localhost:8000');

Essentially, this Node.js application waits on port 8000 for an HTTP request. Once it receives the request, it calculates prime numbers up to 500 and returns the results to the caller (in this case, in a Web browser application).

Microsoft is optimistic about the future of Node.js applications on Azure. The growing community, the power of Node.js and the scale of Azure add up to a compelling offering. JavaScript developers are no longer limited to client-side scripting. Node.js is also fueling the adoption of patterns that are becoming a common practice in the cloud, like CQRS (Command Query Responsibility Segregation), which promotes the separation of read and write operations, in many cases through the implementation of an event-driven architecture. Writing a distributed system in Node.js is easy because of its asynchronous and disconnected nature.

The world just got better—one language can now be used for both server-side and client-side software development, and it can be scaled to support any number of users.


Bruno Terkaly* *works as a developer evangelist for Microsoft. His depth of knowledge comes from years of experience in the field, writing code using a multitude of platforms, languages, frameworks, SDKs, libraries and APIs. He spends time writing code, blogging and giving live presentations on building cloud-based applications, specifically using the Azure platform.

Thanks to the following technical expert for reviewing this article: Ricardo Villalabos.