Microservices

WHITE
PAPER
Microservices
Content
03
04
06
09
10
INTRODUCTION
WHAT ARE MICROSERVICES?
WHAT IS THE USE CASE FOR SUCH A SYSTEM?
BENEFITS AND CHALLENGES OF A MICROSERVICES ARCHITECTURE
COMMON ARCHITECTURAL PATTERNS
HOW BUILDING SUCH A SYSTEM AFFECTS THE ORGANIZATION?
NOTABLE EXAMPLES
CONCLUSION
Introduction
Microservices is possibly the most frequently used buzzword in the recent history of software development. It is a buzzword, because there are a lot of misunderstandings as to what
it actually is, which can lead to the misconception that microservices is the answer to all other problems.
In this whitepaper we discuss the benefits and challenges of using a microservices architecture, while elaborating on the use case we believe to be the most suitable. On the other hand,
also when applying this method in the right situation, the industry’s best practices must be
applied to ensure a successful implementation.
What are microservices?
Microservices are small, independent applications that work together to accomplish business goals. Each microservice runs within its own process, often deployed within a container
or a separate virtual machine. Thereby their functionalities are exposed using lightweight
mechanisms such as ReST-ful API.
The services are built around business capabilities, where one or more services support a
part of the business process and its applicable objectives, e.g. billing, customer relations, invoicing etc. The boundaries of microservices are shaped by the business domain model. The
general guideline is that a microservice is built around a business entity and any additional
objects that provide further information to the business entity, for example: both order and
order item domain objects would be part of an ordering service.
Together, microservices form a distributed system that requires centralized management of
the individual service instances – service configuration, registration and discovery, health
and metrics monitoring, log aggregation and log tracing.
To effectively manage the complexity of a microservices system, a fully automated continuous delivery pipeline for building, testing and independent deploying of each microservice is
required. This setup will greatly help development teams to deliver new microservices in a
minimal amount of time, while keeping productivity at a high level.
3
What is the use case for such a system?
Using a microservices architecture is best suited for organizations that already have a mature business domain supported by a complex and costly monolithic system, which is difficult
to scale. Complexity that warrants a migration to microservices can also come from the necessity to support many different user interaction models, multi-tenancy or the sheer size
of the development team(s) involved in building and maintaining the (complex) monolithic
solution.
When deciding whether to use the microservices approach to build a new system, the team
should consider whether the system needs to deliver content to various consuming platforms (desktop, mobile, 3rd party systems) in a highly available and fault-tolerant manner.
Benefits and challenges of a
microservices architecture
Benefits
• Systems are inherently scalable, as the services built this way are loosely coupled. The
scalability is improved further, if the communication between the services is asynchronous.
• Cross-functional teams organized around small, functionality oriented services lead to a
greater team productivity and less dependencies between the teams.
• Embracing polyglot technology principles enables choosing the right tool for the job.
• Due to independent scaling of microservices, only that which is required to the necessary
degree, will be scaled up, which significantly reduces the cost of infrastructure.
• The application is built for fault tolerance; one defective node does not bring down the
entire system.
4
Challenges
• Operational costs could become significantly higher for systems with high complexity.
• Orchestration of the distributed system adds to the complexity of the system and the
required infrastructure. This includes service registration and discovery, centralized log
tracking and call tracing, integration between the services, data consistency across the
databases for individual services etc.
• The implementation of microservices needs to take fault tolerance into consideration to
be able to combat network latency and non-operational nodes. This adds to the complexity of the services and their code base.
• Cross-functional teams require a greater span of high quality skills: besides software architecture and development, test automation and infrastructure automation (DevOps)
are critical to a successful delivery.
• The distributed nature of the system introduces additional challenges in testing the system end-to-end.
5
Common architectural patterns
The following is a brief overview of architectural patterns that can be applied to combat the
challenges of a microservices architecture.
Microservice template
As systems involve various cross-cutting functionalities - logging, monitoring, registration
and discovery, as well as configuration – all these can be grouped into a microservice template to be used to create each new service for the system. Depending on the implementation technology, cross-cutting functionalities can be offered as configurable open-source
libraries. Adopting this pattern, teams are able to quickly and easily get started with the development of a new service. The downside is increased difficulty for the teams to adopt a
new technology or framework, as this usually requires developing and maintaining a separate microservice template.
Externalized configuration
Externalizing a complete microservice configuration within a central place, such as DB, separate service, OS environment variables, or a combination of all the above, allows clear separation of the implemented functionalities from the environment on which they are running.
Infrastructure automation ensures that microservices receive the appropriate configuration
for the environment where they are deployed, decreasing the time spent on correcting configuration issues on new releases and reducing redeployment. As a cross-cutting functionality, externalized configuration can be part of a microservice template.
Event-driven communication
As services are built around their own databases, there will be functionalities that will span
between services and will require maintaining data consistency across the services. By using
the event-driven approach, where each service publishes an event while its data is updated
and the services interested in these changes are subscribed to these events, we can ensure
that the system reaches eventual data consistency. In order to be reliable, a service must
atomically update its database and publish the event.
One approach is to use application events, where the service inserts events into a database
table as part of the local transaction. A separate process checks the table and publishes the
events to a message broker. Alternatively, the teams can opt for implementing an event
sourcing pattern, together with the Command Query Responsibility Segregation pattern.
6
Event sourcing & CQRS
Applying event sourcing involves persistence of a sequence of state-changing events, which
can be replayed to determine the entity’s state. Whenever the state of a business entity
changes, a new event is added to the list of events.
Application events persist in an event store, i.e. a database of events. The store has an API
for adding and retrieving an entity’s events. The event store also behaves like a message broker; it provides an API that enables services to subscribe to events. When a service saves an
event in the event store, it is delivered to all the interested subscribers.
The main drawback of this approach is the complexity and inefficiency involved in querying
the event store for a specific entity state. The CQRS (Command Query Responsibility Segregation) patterns help by splitting the functionalities into a command aspect for handling
the creation, update and deletion of operations, and a query aspect responsible for handling
the data queries. The command side emits events on any data updates, while the query side
is subscribed to these events and keeps the local latest state of the interested entities for
querying. These are usually implemented as separate microservices.
API gateway
The API gateway is a single entry point to the system for all its clients. The gateway handles
requests by proxying a request to the appropriate service or by transforming a single client’s
request to multiple requests towards different services in order to fully service the client. It
can also expose versions of the API tailored to a specific client, as device-based clients tend
to require less data than their desktop counterparts.
Besides hiding the complexity of a distributed system from the clients and providing an optimal API for each client, the API gateway can also perform an authorization rule check and
determine whether the client is allowed to perform the request.
Service registration and discovery
A modern microservice-based application usually runs within a virtualized or containerized
infrastructure, most likely within a cloud environment. Within this environment, locations of
the services are dynamic and often change, especially when new instances of the services are
added to satisfy the system’s performance requirements.
When making a request to a service, the client can obtain the location of a service instance by
querying a service registry, which knows the locations of all service instances. Alternatively, the client can make a request via a router or load-balancer, which is available on a wellknown location, and the router will obtain the location of the destination service to which
the call is made.
7
Having discovery performed by the client results in less system components and calls over
the network, while using the specialized router or load-balancer decouples the client from
service registry and keeps the client’s code base simple.
A service registry is a database of services, their instances and their locations. Service instances are registered with the service registry on startup and deregistered on shutdown.
The service registry is a critical system component and needs to be highly available on a fixed
and well known location, so it can be reliably queried.
The services can either be responsible for registering themselves or can depend on a 3rd party to perform the registration. When self-registration is used, the service instance registers
itself (host and IP address) with the service registry on startup and makes itself available for
discovery. The service usually periodically renews its registration so that the registry knows
it is still up and running. On shutdown, the service instance unregisters itself from the service
registry.
Using 3rd party registration involves a specialized component in the system called registrar,
responsible for registering and unregistering a service instance with the service registry.
This approach keeps the client simplified as opposed to self-registration, where the client
needs to be aware of the service registry and is coupled to it. As a drawback, the registrar is
yet another system component that needs to be deployed, configured and maintained.
Circuit breaker
This pattern allows services to handle network failures and prevents a failure of one service,
so not to propagate it to the rest of the system. This is accomplished by keeping track of
failed calls between two services and - once successive calls fail a preconfigured number of
times - the circuit breaker is triggered to make any further calls immediately fail. After a preconfigured time lapse, the circuit breaker will allow a limited number of test requests to go
through, and - if these succeed - the circuit breaker will resume normal operation. The most
important feature introduced by the circuit breaker is the prevention of lagging, making the
system more responsive and robust.
8
How building such a system affects the
organization?
According to Conway’s law, the communication structure of an organization is translated to
the structure of the information system developed by that organization. Thus, in order to
successfully deliver a distributed system based on a microservices architecture, the organization needs to adopt cross-functional teams, the DevOps culture and agile software development practices.
The teams are grouped around business capabilities and take ownership and responsibility
for the services that implement these capabilities. The teams are highly autonomous in developing and deploying new versions of the services, making possible for the different business functions to evolve independently. Each team possesses a great variety of development,
testing and infrastructure automation skills to be able to fully deliver services, from the initial design to the deployment on a live environment.
Notable examples
Netflix is perhaps the best-known example of a company moving from a monolith system towards a microservices architecture. During the migration, Netflix development teams built
a number of tools and technologies to simplify the development of microservice systems.
These tools have been made open source: Netflix Zuul (API gateway), Hystrix (Java library
for latency and fault tolerance, based on the circuit breaker pattern) and Eureka (service registry).
Besides Netflix, other companies faced with the increasing complexity of monolith systems
have also decided to migrate to a microservice solution: Amazon, eBay, SoundCloud, Wehkamp, Uber etc.
9
Conclusion
While the microservices architecture is not a cure for all ills, and using it for smaller systems and organizations is simply making things too complex, it certainly brings great benefits
when high scalability and fault tolerance are a must. By applying the aforementioned architectural patterns, the challenges of such systems can be addressed, whereby a migration to
microservices can mean further modernization of your IT.
10
Levi Nine is a Dutch IT Services
company with currently over
850 highly educated and skilled
IT professionals in Eastern and
Central Europe.
Our teams work remotely on
software products and revenue
generating systems for Dutch
and International clients. We
are the technology partner for
clients that are looking for reinforcement and a flexible layer
of their own IT department,
or are looking to co-source or
outsource IT development and
maintenance.
Levi Nine is strong in the area
of common software R&D, software product development and
client implementation projects.
We strongly believe in DevOps
principles, Infrastructure and
Test Automation and Continuous Delivery.
We work for industry leaders
such as TomTom, bol.com,
Drukwerkdeal, WoodWing,
Sanoma, Xerox and Swarco.