Microservices Architecture
Microservices Architecture
Microservices are becoming more and more popular. Nowadays, pretty much every
engineer on a green field project should be considering using microservices in order to
improve the quality of the systems they build. They should know the architectural
principles involving such systems. We will expose the difference between microservices
and Service-Oriented Architecture (SOA). We will also introduce a great platform to write
microservices, Node.js, which will allow us to create high-performing microservices with
very little effort.
Monolithic software
The natural trend for new high-tech companies such as Amazon or Netflix is building
their new software using microservices, which is the ideal scenario: they get a huge
advantage of microservices-oriented software (through out this book, you will learn
how) in order to scale up their new products without a big effort. The problem is that not
all companies can plan their software upfront. Instead of planning, these companies
build software based on the organic growth experienced: few software components
group business flows by affinity. It is not rare to see companies with two big software
components: the user-facing website and the internal administration tools. This is
usually known as a monolithic software architecture.
Some of these companies face big problems when trying to scale the engineering teams.
It is hard to coordinate teams that build, deploy, and maintain a single software
component. Clashes on releases and reintroduction of bugs are a common problem that
drains a large chunk of energy from the teams. One of the solution to this problem (it
comes with benefits) is to split the monolithic software into microservices so that the
teams are able to specialize in a few smaller modules and autonomous and isolated
software components that can be versioned, updated, and
deployed without interfering with the rest of the systems of the company.
Splitting the monolith into microservices enables the engineering team to create isolated
and autonomous units of work that are highly specialized in a given task such as
sending e-mails, processing card payments, and so on.
A microservice is an autonomous unit of work that can execute one task without
interfering with other parts of the system, similar to what a job position is to a company.
This has a number of benefits that can be used in favor of the engineering team in order
to help scale the systems of a company.
Nowadays, hundreds of systems are built using microservices-oriented architectures, as
follows:
• Netflix: This is one of the most popular streaming services, it has built an entire
ecosystem of applications that collaborate in order to provide a reliable and scalable
streaming system used across the globe.
• Spotify: This is one of the leading music streaming services in the world, it has built
this application using microservices. Every single widget of the application (which is a
website exposed as a desktop app using Chromium
Embedded Framework) is a different microservice that can be updated individually.
Microservice-oriented architectures
Microservices-oriented architectures have some particularities that makes them desirable
for any mid/large-sized company that wants to keep their IT systems resilient and in
scale up/down-ready status.
How is it better?
They are not the holy grail of software engineering, but, when handled with care, they become
the perfect approach to solve most of the big problems faced by tech-dependent companies.
It is important to keep the key principles of the microservices-oriented architecture's design in
mind, such as resilience, composability, elasticity, and so on; otherwise, you could end up with a
monolithic application split across different machines that produces problems rather than an
elegant solution.
Shortcomings
There is also some criticism around microservices-oriented architectures, as they
introduce some problems to deal with, such as latency, traceability, and configuration
management that are not present with monolithic-based software. Some of the problems
are described as follows:
• Network latency: Microservices have a distributed nature so that network latency has to
be accounted for
Operations overhead: More servers indicate more maintenance
• Eventual consistency: On highly transactional systems, we need to factor into
implementation the fact that the data could be inconsistent during a period of time (we
will talk about it later in this chapter)
In general, engineers should try to evaluate the pros and cons of this approach and make
a decision on whether to use microservices or not in order to fit the business needs.
Microservices-oriented architectures have some particularities that need to be taken
into consideration. When a software engineer is writing monolithic software, there are
some problems that are completely overlooked due to the nature of the software
being built.
For example, imagine that our software needs to send e-mails. In a monolithic software,
we would just add the functionality to the core of the application. We might even choose
to create a dedicated module to deal with e-mails (which seems like a good idea). Now,
imagine that we are creating a microservice and, instead of adding a functionality to a
big software artifact, we create a dedicated service that can be deployed and versioned
independently. In this case, we will have an extra step that we didn't have to take into
consideration, the network latency, to reach the new microservice.
In the preceding example, no matter what approach (monolithic or microservices) you
are taking to build the software, is not a big deal; for example, if an e-mail is lost, it is not
the end of the world. As per definition, the e-mail delivery is not guaranteed, so our
application will still work, although we might receive a few complaints from our
customers.
Another difference between microservices and SOA is the technologies used for
interconnecting and writing the services.
J2EE is a technology stack that was designed to write SOA architectures as it enforced
enterprise standards. Java Naming and Directory Interface, Enterprise Java Beans, and
Enterprise Service Bus (ESB) were the ecosystems where SOA applications were built
and maintained. Although ESB is a standard, very few engineers who graduated after
2005 have heard about ESB, even fewer have used it, and nowadays the modern
frameworks such as Ruby on Rails do not even consider such complex pieces of
software.
On the other hand, microservices enforce the use of standards (such as HTTP) that are
broadly known and broadly interoperable. We can choose the right language or tool to
build a component (microservice) following one of the key benefits explained earlier in
this chapter, in the Technology heterogeneity section. Aside from the technology stack and
the size of the services, there is an even bigger difference between SOA and
microservices: the domain model. Earlier in this chapter, we have talked about
decentralization. Decentralization of the governance, but, moreover, decentralization of
the data. In a microservices-based software, every microservice should store its own data
locally, isolating the domain models to a single service; whereas, on an SOA oriented-
software, the data is usually stored in a few big databases and the services share the
domain models.
Why Node.js?
A few years ago, I didn't believe in Node.js. To me, it was a trend more than a real tool to
solve problems… JavaScript in the server? That didn't look right. In all fairness, I didn't
even like JavaScript. Then, the modern frameworks such as jQuery or Angular.js came to
the rescue. They solved one of the problems, which was the cross-browser compatibility.
Where before we needed to factor in at least three different browsers, after jQuery all this
logic was nicely encapsulated in a library so that we didn't need to worry about
compatibility as long as we followed the jQuery documentation. Then, JavaScript
became more popular. Suddenly, all the internal tools were written with Single-Page
Application (SPA) frameworks with a heavy usage of JavaScript,
therefore, the majority of developers nowadays, one way or another, are proficient in
JavaScript.
Then, someone decided to take JavaScript out of the browser, which was a great idea.
Rhino, Node.js, and Nashorn are examples of runtimes that can execute standalone
JavaScript. Some of them can even interact with the Java code, enabling the developer to
import Java classes into a JavaScript program, which gives you the access to an endless
set of frameworks already written in Java. Let's focus on Node.js. Node.js is the perfect
candidate for microservices-oriented architectures for a number of reasons, as stated in
the following list:
• Easy to learn (although it can be hard to master)
• Easy to scale
• Highly testable
• Easy to deploy
• Dependency management through npm
• There are hundreds of libraries to integrate with the majority of standard
Protocols These reasons, along with others that we will develop in the following
chapters,
make Node.js the perfect candidate for building solid microservices.
Summary
In this chapter, we studied the key concepts around microservices, as well as the best
practices to be followed when designing high-quality software components towards
building robust and resilient software architectures that enable us to respond quickly to
the business needs.
You have also learned the key benefits such as the possibility of using the right language
for the right service (technology heterogeneity) on the microservices-oriented
architectures as well as some of the pitfalls that could make our life harder, such as the
overhead on the operational side caused by the distributed nature of the microservices-
oriented architectures.
Finally, we discussed why Node.js is a great tool for building microservices, as well as
how we could benefit from JavaScript to build high-quality software components
through techniques like API aggregation. In the following chapters, we will be
developing the concepts discussed in this
chapter, with code examples and further explanation about the topics I have learned
over the years.
As explained before, we will focus on the V8 version of JavaScript, but I will provide
some hints on how to easily write upgradeable components to embrace
ECMAScript 6.