Building microservices with Node.js

Why build monoliths when you can compose applications from services? Here are some guiding principles for using Node.js and the Seneca framework to create microservices apps

Microservices architecture may be the most important trend in modern enterprise application development. Instead of massive monolithic applications, with their hefty maintenance and infrastructure overheads, microservices-based applications break up functionality into a suite of small services, linking them via APIs. That approach enables elements of an application to be updated and scaled separately.

The most important feature of a microservices architecture is its array of APIs, often built using familiar HTTP-based RESTful techniques, pushing JSON payloads between services. Each service is a single element of functionality and can be built using the most appropriate technology. One might be written In C#, another integrated into a NoSQL database, another a JavaScript UI running in a browser. The result is a service architecture that works well with modern mobile-first application development methodologies and can be easily integrated into a continuous development devops process.

Many popular websites and services are built using a microservices model; Amazon serves as a prime example. At Amazon, small devops teams are responsible for building and maintaining the services that run the site, with 200 or so services coming together to deliver the Amazon home page. The microservices model also means it’s possible to improve service performance one service at a time, a process that Box calls “ratcheting”: setting targets for developers to improve service responsiveness as the company defines targets for agile development sprints.

Component-based models like microservices are a way of delivering composable applications, with services reused across applications thanks to well-documented, explicit APIs. While this is an efficient way of designing applications, it’s not an efficient way to deliver them. There are overheads in RESTful API calls, especially when you’re using them as a mechanism for handling remote procedure calls.

Part of that is the overhead of running a Web server to handle your services, with separate instances needed for each separate service running on a server. That can be an issue if you’re planning on building a high-density set of services, with each microservice running in a separate container or VM. That’s where a lightweight server comes in to play, replacing the heavyweight Apache or IIS with a more service-oriented item.

One option is Node.js (or its compatible fork, io.js). It’s lightweight, responsive, and designed to work well with common Web data types, including JSON. Its combination of features makes it an ideal host for microservices, enabling you to build services quickly using Node.js as a switching service that processes and routes JSON between APIs. It’s often easiest to think of Node.js as a software router, handling messages and processing responses -- an ideal structure for a lightweight service architecture.

While it’s easy enough to build your own Node.js service framework (either writing custom code or using one of the widely available MVC frameworks like Express), it’s easier to use a Node.js-specific microservice framework such as Seneca to quickly build prototypes and minimum viable products.

Seneca is an interesting tool that aims to replicate the way architects and developers think about services, offering ways to organize code into logical actions that are triggered by patterns, which are in turn modeled after use cases. Once they’ve been defined, patterns are easy to turn into APIs, with the use cases and patterns defining the message content.

As patterns implement use cases, they also let you see where business logic needs to be added. For example, if you’re building an airline booking service and have a passenger details pattern, this is likely where you would implement code to handle frequent flyer details and add them to the ticket passenger record, as well as recording the ticket number against the passenger’s frequent flyer account.

Seneca’s developers describe it as a “business logic organizer," an apt description of the way it delivers much of what you need to build a set of microservices. Seneca is extensible via service plug-ins (with implementations for common SQL and NoSQL databases) and by other Node.js modules -- so you can use it with anything you can install using NPM (Node Package Manager). That gives you the option of using Seneca in conjunction with familiar middleware, simplifying the process of taking an existing application and breaking it into services.

While using Seneca and Node.js gives you a framework for a lightweight service architecture, it’s only part of the story because you’ll need to consider your services as part of a scale-out distributed system. That means, in practice, you’ll have to reinvent the SOA (service-oriented architecture) wheel and implement some form of message broker as a tool for delivering messages to a cluster of Node.js services running in containers. One option is to work with an open source MQ implementation, using it to take messages from various sources and route them to Node.js services via publish and subscribe protocols. It’s certainly easier than writing your own scale-out message router!

Once you’ve started using tools like Seneca to build microservices, you’ll then build them into a test and deployment devops workflow. Building and deploying a service-based application is all very well, but it can’t be left to languish unmaintained. You’ll also implement some form of continuous delivery model around your services, and use it to manage and roll out updates -- a harder problem than writing code.

Building modern applications with microservices makes sense, as it lets you take advantage of both scale-up and scale-out architectures, with the bonus of composable APIs that can be reused throughout your businesses. You may not end up delivering new services every minute or so, like Amazon does, but you will have an agile and responsive application platform that will keep improving.

Copyright © 2015 IDG Communications, Inc.