Every architecture is formed based on certain design principles and Microservices is no different. This article will not talk about what Microservices is all about. There are already plenty of articles and blogs to do that. In this article, I will talk about what it takes to devise a Microservices based architecture. We will take a look at some of the design principles one should take into account to design a Microservices based applications.
Services must be designed to work in isolation. When you break up a monolithic system into set of services, it is necessary that these services are decoupled from one another, are made more cohesive and self sufficient. Each service should be able to handle its failure without breaking the whole application or system. Isolating and decoupling enables service to recover itself from the failure condition very quickly. The isolation characteristic of the service has the following benefits: easy adoption of continuous delivery, better scaling, effective monitoring and testability.
Isolation paves the way for autonomy. Services must be designed to be autonomous. It must be cohesive and able to fulfill its function independently. Every service can be independently invoked using a well defined API (URI). The API in a way identifies the service function. Autonomous service must also deal with its own data. More popular term is polyglot persistence where each service has its own persistence store. Autonomy also ensures resiliency. An autonomous service has the following benefits: Effective service orchestration and coordination, better scaling, communication through well defined API, faster and controlled deployment.
Service must be designed to be highly cohesive. A single responsibility principle is where the service performs only one important function. The single responsibility aspect gels well with the term ‘micro’. Micro indeed means small, fine grained and only relevant within its scope of responsibility. The single responsibility feature has the following benefits: Services composition is seamless, better scaling, reusability, extensibility and maintainability.
How big or small your services should be? Million dollar question? Well the answer lies in what is called as Bounded Context design principal. It is a key pattern while devising a Domain Driven Design (DDD) modeling approach. Bounded context is all about defining a context in which your Microservices will be providing its services. It is about evaluating your domain model and identifying discrete boundaries and accordingly designing your Microservices to make it more cohesive and autonomous. That also means communication across boundaries becomes more efficient and your service in one bounded context need not be dependent on service in another bounded context for too many things.
While drawing discrete boundaries and designing services with its own bounded context, it is necessary that service communication across boundaries must be asynchronous. The asynchronous mode of communication naturally leads to loose coupling between services and allows for better scaling. With synchronous communication, you are blocking a call and waiting for the response. A service in a blocking state cannot perform another task until the response is received and the underlying thread is released. It leads to network congestion and impacts both latency and throughput. Asynchronous communication can also bring in the notion of implementing a well defined integration or communication pattern to achieve a logical workflow involving different services.
Microservices, by design, are good candidates to be deployed in a virtualized environment or docker containers. With the advent of cloud computing, we can have plethora of service instances that can take advantage of dynamic scaling environment. The services could be running on multiple nodes across small or large clusters. Services itself can be relocated depending upon the availability or efficiency of the underlying computing resource. One must be able to address or locate the service in a location independent manner. Often different lookup discovery patterns can be used to consume your service. The client or consumer of the service does not have to bother about where a particular service is deployed or configured. It just uses some kind of logical or virtual address to locate the service. For more information of service discovery, you can refer to the Service Discovery Patterns article.
Microservices is not a technology, framework or a solution. It is an architectural style that provides you an approach or methodology to deal with the complex nature of a monolithic application. The approach starts with the above design principles that you can use to architect Microservices based application.
A good heads up on Microservices by Martin Fowler can be found at: http://www.martinfowler.com/articles/microservices.html