Part 1
of this article describes application modernization. This section deals with
microservices architecture that suits application modernization very well. Microservices
break away from the monolithic architecture which has been the norm in legacy
systems for a while. Monolithic applications tend to grow indefinitely which
also increases the complexity. Finding bugs and creating new features take a
long time. If a part of the application needs to be updated, the whole application
must be restarted which can mean a considerable down time for large systems.
Monolithic applications are harder to deploy since some parts of the
application might have different requirements. Some parts are computationally
heavy, and others are memory heavy. The one-size-fits-all environment to
satisfy all requirements of the application is usually expensive and
suboptimal. They are not scalable. A
peak in traffic can lead to failures from various components. If the number of
instances of the entire application is increased, it wastes resources. These
systems do not evolve fast because they are locked in technology. The same
programming language and framework must be used from the first to the last
module.
Microservices are self-sufficient processes that can
interact with other microservices to form a distributed application. Generally, a ring of microservices is
developed that are small independent services that have their own isolated
environment with operating systems, databases and other support software. Each microservice might be dedicated to a
distinct set of resources that it supports with create, update and delete
operations. They often use message passing via web requests to communicate with
one another. Each microservice can be built with different programming
languages and different environments depending on the requirements.
Microservices facilitate cross-functional team organization
and based on business capabilities. This leads to faster delivery and higher
quality due to testability and focused effort. This avoids the immense
cross-team interactions from component-based software development. It also avoids
developers from writing logic in the layer that is closest to them be it
user-interface, service, or database.
Cloud service platforms have made operating and deploying
microservices based applications easier and cheaper. It allows teams to build
microservices using continuous integration and continuous delivery. The
pipeline automates testing, building, developing, deploying and delivering the
microservices. Updates to one microservice does not affect the others. But when
a single microservice goes down, it can have a cascading effect on other
services because they have high fault density. This is true also for components
that grow in size. This is generally overcome by keeping microservices focused
and small.
The reliability of microservices is dependent on the
reliability of the communication between them. Http and protocol buffers are
the communication protocols of choice. Development and deployment are also
owned by the same team. This idea is inspired by Amazon’s “you build it, you
run it” philosophy. The transition to microservices from legacy monolithic code
is not straightforward. The functionalities must be separated beyond components.
And in the process of doing so, we cannot risk regression. Tests become a way
to scope out behavior at boundaries such as interface and class
interactions. Adequate coverage of tests will guarantee backward
compatibility for the system as it is refactored. The microservices are
independently testable both in terms of unit tests as well as end-to-end tests.
The choice and design of microservices stem from the minimal
functionalities that need to be separated and articulated. If the services
don’t need to be refactored at a finer level, they can remain encapsulated in a
singleton.
The rule of thumb for the refactoring of the code is the
follow up of the Don’t Repeat Yourself or (DRY) principle which is defined as
“Every piece of knowledge must have a single, unambiguous, authoritative
representation within a system”. This calls for every algorithm or logic that
is cut and pasted for different usages to be consolidated at a single point of
maintenance. This improves flexibility because enhancements such as the
use of a new data structure can be replaced in one place and it also
reduces the bugs that come by when similar changes must be made in
several places. This principle also reduces the code when it is refactored
especially if the old code had several duplications. It provides a way to view
the minimal skeleton of the microservices when aimed at the appropriate scope
and breadth. Even inter-service calls can be reduced with this principle.
- courtesy Kristian Tuusjärvi
No comments:
Post a Comment