Microservices are components of an application developed as independent services. The concept of microservice is all about breaking down your application into independent set of services. Often when writing a monolithic application, the code base can grow quickly and in spite of being well-structured, debugging, performing changes, applying fixes and deploying can become challenging and nightmarish.
One approach obviously is to apply appropriate design patterns like ‘High Cohesion’ that makes every component of an application look more functionally independent and the application itself more cohesive. But this form of cohesiveness is more component driven than business. As you write more code, more dependencies are added and it can break the very fabric of cohesion.
Monolithic applications can be envisioned with the new architectural concept based on microservices. Application can be decomposed into small independent services based on domain functionality. The service code can be a set of business functions that speaks one domain vocabulary. The advantage of course is drawing a strict domain boundary and keeping the codebase small and restricted to that domain functionality. An application overall forms a perspective of small services than one large codebase.
“The microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.” – As stated by Martin Fowler
One question often asked at various forums and presentations on microservices is: How small your services should be? A service written in a traditional construct-like language may have more lines of code than say a service written in a more modern scripting-like language. Given this fact, it also depends on how you wish to decompose your application. It’s a classical OOPS Abstraction phenomena! A chessboard of 64 squares, whether you perceive it as 4 large squares of 16 or 16 squares of 4 each. Your service should neither be too small or too big. It should just about focus on the domain functionality that is addressed in few lines of code. The codebase of the service should not grow after a goal of addressing a business functionality is achieved. The term ‘micro’ can be misleading. Breaking your application into a very small fine grained services (probably even breaking each module) could lead to complexity in development and deployment if there arises too much inter-dependencies.
Each service should be an independent entity capable of being deployed in isolation of other service bundles. Often the deployment itself should be distributed in nature and not tied to a single tier. A more prevalent example is of PaaS which offers a platform, to build and deploy your application, as collection of services. Encapsulation is the key when developing microservices. A service should consist of code which can be easily changed without affecting other services. If your service contains common code not tied to a service functionality, it could lead to tighter coupling with other services which can affect the modularity and make the deployment a more complex affair.
A well-defined communication pattern should be devised in order for service to talk to each other. One such pattern is the API based communication. The concept of API has become more prominent with the advent of RESTful services. Each service can be envisioned as a RESTful service which can talk to other service through a well-defined API using a URL. The communication pattern should be technology or language agnostic. Only the relevant aspects of the service should be exposed as API and the rest should be conveniently encapsulated.
Key Advantages of Microservices based Architecture
More technology and tool options
As discussed earlier, each service should be developed as an independent entity and therefore the choice of programming language or technology involved should not matter. We should be able to choose the most viable or appropriate technology option to write the service. This eliminates the culture of writing in only one programming language or follow a specific standard that could lead to a more tightly coupled architecture. Sometimes there are technologies that offers greater performance or flexibility and we should be able to use that to develop our service and not restrict to a particular technology.
Because each service is independent of each other, adapting to new technology or completely replacing the technology for that service is more easy and acceptable. Imagine an application developed using a framework ‘A’ which goes obsolete in few years. Now replacing ‘A’ with the new framework say ‘B’ would involve a complete rewrite of the application. If your application is divided into independent services, one can make a choice of technology or language that makes it more convenient to write the service and even more so if it has to offer greater performance benefit.
Mixing technologies also has its fair share of concerns. Technologies written for one particular environment and services developed around that environment could scale easily but if any one of its service uses the technology not part of that environment it could lead to difficulties in devising a right communication pattern. All in all, a polyglot style of programming should be the order of the day when envisioning a microservices architecture.
Ability to handle failure condition
Systems are made to fail. System or machine failures are handled through appropriate clustering and fault tolerance design. A monolithic application going down can have a wider impact. All the important functions are unavailable until the application is looped back to normal. Recovery from a failure condition often becomes too tedious, complex and slow. The microservices design helps you recover the application quickly and healthily.
As the services are autonomous and independent of each other, one service going down does not impact the whole system. For example, an ecommerce web application could have say two services running for its home page: 1. Listing of products 2. Mini dashboard showing the store activity. If say, the second service goes down, one can still view the product listing while the dashboard can simply flash a message ‘We will be back soon’.
On demand provisioning and scaling
The idea of microservices easily translates into cloud. Every cloud vendor will have an on-demand provisioning facility where you could provision for resource quickly when needed. The same concept applies to services. Each service can be provisioned and therefore auto-scaling can be applied only to that service. You only pay for what you provision. Imagine if you have to provision complete monolithic system and make it auto scaled, it can increase your cost three-fold. With microservices architecture, you only pay for service that you feel is important to provision and scale.
Ease of deployment
We discussed this earlier, a large monolithic application can be tedious to deploy. One change and the complete application undergoes build and deploy process. Often a large codebase takes hell lot of time to build. For many large complex system, it could take hours to build and deploy the change. So the obvious process is to aggregate all the changes and deploy the same at a later time (often scheduled). Now this approach could get error prone. If there is any error found during the test (or for that matter even during build), it has to undergo the bug fixing or rollback process and again undergo a complete build cycle before it is deployed. This affair can get frustrating for the developers and release managers.
With microservices, you can avoid building the system as a whole. You only build service that has undergone changes keeping the rest of the system untouched. It makes your deployment faster, smoother and cleaner. If there occurs any problem within that service, rolling back or fixing it becomes easy as it is done in isolation independent of other services.
Modular approach to development
When you have large codebase, the development process can take a toll. Often a large team is working on different pieces of code that could lead to issues with configuration management. It is always recommended to the divide the application into modules of importance and development team can then be formed to handle each module. Microservices architecture automatically fits into modularity approach. Because each service provides a specific domain functionality, we could have development team structured based on domain modules. It can bring in lot of productivity and efficiency in the overall development process.
Services by definition are self-contained and reusable components. With microservices, we build a service functionality that can be perceived and used by many external applications. The service itself is reusable. Apart from being inherent part of the system or application, it can also be exposed to the outside world. A traditional tightly coupled architecture may have components that can be reused only within the confines of that application. Microservices architecture goes a step forward and allows you to envision a service that can be made reusable enterprise wide and across organizations.
Every organization probably will have one large traditional legacy system that is waiting to be decommissioned. Imagine the cost and time associated with the migration. A microservices based architecture makes your system easily replaceable. The whole system is composed of mini services and each service can be easily replaced with the new implementation when required, thereby minimizing the cost, time and increasing the overall application manageability. Rewriting a service is more easy and manageable than rewriting the whole application. One can also quickly decommission an old service and easily replace it with a new service.
SOA and Microservices
Service Oriented Architecture (SOA) is a set of design principles where multiple services form an orchestration to fulfil a business goal. Microservices is one approach towards implementing SOA. The very concept of SOA emerged to tackle the challenges involved in the traditional tightly coupled architectures. The whole objective of SOA is software reusability. The concept of SOA is often too heavyweight to digest. Many organization till today struggle to understand and realize the SOA architecture. SOA itself needs introspection when it comes to messaging protocol like SOAP, service granularity, service interoperability and middleware solutions. Microservices on the other hand is a natural and easy way to achieve SOA. It’s a minified SOA where one takes gradual steps in forming a service based ecosystem.
The article talked about microservices as autonomous components developed as services. They are small domain specific functions as services that together makes up a complete system. They are negotiated using a well-defined API. Some of the advantages of microservice based architecture include ease of deployment, reusability, modularity, easy scaling and manageability.