As the pace of IT technology
evolving and its dynamic nature increased, more scalable and durable
architecture for solution become relevant. As time went by we came across
single tier standalone applications to distributed computing models like client
server architecture, N-tier application architecture, Service oriented
Architecture to build stable and durable and maintainable solutions. However
many of these architecture was having limited life span due to its co-related bindings
or tightly coupled nature. Lot of these architecture has limitation to scale par
with the usage needs or resilience. Time has reached to re-think of the
sustainability of architecture that avoid complete rewrite with technology
changes and support patching and resilience for durability and scaling.
Microservices is an approach
to application architecture in which a large application is built as a suite of
modular services. Each module supports a specific business goal and uses a
simple, well-defined interface to communicate with other modules. Because
of the modularity this architecture not only increase the reusability also
support to scale out nature, maintainability and sustainability.
Principle behind Microservices
Microservices are based on Scale
Cube principle for scalability which emphasis on the Y axis Scaling – An
approach of modularizing a program based on its verb nature or noun
characteristic of functions. For example “Login mechanism” is a verbal
function, “Payment gateway” is a noun function.
Microservices also emphasis is
Single Responsibility Principle (SRP) which help to decouple a unit function
and give it an identity and hence it can be reused.
Another principle is based on the
light weight interfaces that the services use to communicate with the external
components or users.
Yet another principle to ensure
the identity of a Microservice is Self-contained system. An autonomous,
isolated unit that includes its own data, logic, and UI.
Scalability
Other than Y axis Scaling X and Z
axis scaling also are considered in Microservices architecture to bring out the
higher potential of scaling and application rigidity and high availability.
X Scaling is a way of scaling by
replication of the same instance in a kiosk way so that the requests will be
load balanced.
Z Scaling is a way of data
sharing-based approach. When using Z-axis scaling each server runs an identical
copy of the code. In this respect, it’s similar to X-axis scaling. The
difference is that each unit is responsible for only a subset of the data. Many
a time a routing mechanism is used to route the query to the specific subset of
data.
Single Responsibility
Principle
SRP is derived as the principle
behind object oriented programing the way how a class is derived. The intention
behind using SRP in Microservices to design the services with maximum
modularity so that it can be reused , scale and maintain than an interrelated
service, this Microservices are modular, compose able and fine-grained units
that do one thing and one thing only.
Light weight
interfaces for communication
An asynchronous is the preferred
communication mode for Microservices as it won’t create an IO block in
comparison with a synchronous communication. However there will be situation
where synchronous communication is unavoidable like the database will usually
have to be synchronous in the sense that it happens within the request-response
cycle. Remote calls are more expensive than in-process calls, and thus
remote APIs need to be coarser-grained.
REST APIs are mostly used in Microservices
interfaces. HTTP and REST synchronous calls should be minimized between
Microservices because of its co-related nature. Advanced Message Queuing
Protocol (AMQP) for asynchronous communications are also widely used between
Microservices.
Message bus technologies like RabbitMQ and Apache Kafka for asynchronous communication between
Microservices are also widely used. In case the message-passing is done on the
same host, then the containers can communicate with each other by way of system
calls, as they all share the same kernel.
Containerization
Containers is an
operating-system-level virtualization method for running multiple isolated systems
(containers) on a control host using a single kernel. The Container
concept was first introduced in Linux. Containerization is Light Weight Virtualization,
which will eliminate wastage of resources compared to normal server virtualization.
As Containers will share resources, it results in optimize resources
utilization and void latency due to OS booting.
Each Container will have its own IP and network settings. Containers
extend the decoupling, separating software from the underlying hardware in micro
service architecture.
Containers decouples software
from the underlying hardware, bringing us portability and speed not seen before
in VM-based solutions. Containers are easily packaged, lightweight and designed to
run anywhere. Multiple containers can be deployed in a single VM. Microservices
encourages to decouple our software into smaller functional pieces which are
expected to fail, bringing us agility and resilience. Thus bringing a blend of Microservices
architecture with Containerization will result in better resilience and
modularity for maintenance.
A composition of Containers can
logically form an application. Application orchestrating multiple
containers will achieve the desired output.
Some best practices
while Microservices Design
Asynchronous communication- Avoid
IO blocks using asynchronous communication as much as possible. Using
synchronous communication might cause IO blocks in case the serving service is
not available to complete the loop of communication. Using the asynchronous
pattern the services are more decoupled compared to the synchronous pattern and
which preserves the autonomy of the service. Ultimately, the goal is
for your service to be available to the end-user even if other services that
are part of the whole system are offline or unhealthy.
Clean Separation of Stateless and
State full Services- Microservices scale better when they are stateless. In
such circumstances where we need to use state full services we have to keep persistence
layer or data caching mechanisms.
Avoid Sharing and Avoid Host
Affinity and Reduce dependency- When one or more containers rely on the same
library, it may be tempting to share the dependencies by centrally configuring
them on the host. This model introduces complexities in the long run. It not
only it brings host affinity, but also breaks the Continuous Integration Continuous
Deployment pipeline. Also need to consider to keep only the required
library for the unit of function to work.It is almost impossible to reduce the
dependency due to the atomicity of Microservice, but the design should take
care to reduce the co-related interdependency as much as possible.
Well defined APIs – The APIs
should be well defined for entry and exit, also should have proper exception
handling by the service.
Self-Registration and Discovery
Mechanism using central registry- A central registry is maintained for looking
up all available services. Central service registry is used to handle
registration. The registry plays a critical role in orchestrating Microservices.
Netflix Eureka, Consul
and Apache
Zookeeper are examples of commonly used registries for Microservices.
Benefits of
Microservices Architecture
RAD-From a project engineering
perspective. When the different components of an application are separated, they
can be developed concurrently independently and faster.
Resilience - Rather than relying
upon a single virtual or physical machine, components can be spread around
multiple severs or even multiple data centers and support failovers and hence
continuity.
Scaling-Rather than
scaling up with bigger and more powerful machines, or just more copies of
the entire application, you can scale out with duplicate copies of
the heaviest-used parts.
Polyglot over Single Stack-One
advantage of using Microservices is the ability to choose the best of breed OS,
languages, runtimes and libraries. For example, With Microsoft adding native
container support to Windows, it is also possible to mix and match Linux
containers with Win32 and .NET containers within the same environment so that
.net as well as java programs or shell scripts together can orchestrate an end
to end application.
Code Maintainability-Each micro
service is an Independent unit of code which is configured with identity in
configuration management system. This makes it possible to deploy newer
versions of services without disrupting the application.
Challenges
Basically there are two
categories of problems arising with moving to Microservice patterns. One is
software architecture mindset/pattern related problems, e.g. how do we define a
Microservice, how big or thin should it be, how communication handled, etc.
The other is Testing, deployment and operations
production related problems. The concepts like DevOps are supportive to address
the later to a greater extend.