Application Decomposition using Microservices – An Overview
Over the period of time, we have seen that the maintenance of large enterprise applications has become critical and more complex. As new requirements constantly flow into Development, QA team gets stressed with meeting deadlines and SLAs during every release cycle. Sometimes these issues get overlooked and the system becomes unstable. Distributed Application Development could be a potential solution to mitigate this risk. In distributed application development, conventional monolithic fat applications (WAR or EAR) are decomposed into smaller Microservices. The business goal is achieved by orchestration and choreography of the Microservices. Basically it provides perfect modularity by facilitating independent design, development, deployment and maintenance of modules.
While migrating from existing monolithic application to Microservices, first strategy would be to identify hidden context in the current application. In modular application development, while developing a module, context boundaries are not explicitly defined, entities and codes are shared across modules. Defining contexts and drawing explicit context boundaries help in designing a robust Microservice. For example a typical online shopping mart can have an order and shipping module using the same entity product.
We can easily identify contexts here and can draw context boundaries as below:
Once the context boundaries are defined, it is easier to decompose existing monolithic application into distributed application with one Microservice for each bounded context. Now we have separate product entity in order Microservice and shipping Microservice with their respective repositories. Similar concept can be extended by defining explicit context boundaries for stock and inventory module, by creating an independent Microservice for each.
When you transform a business method that has functions like communication to external system, sending an email or updating something to FTP, these functions should not be migrated into newly planned Microservice. Instead Microservice should only have simple REST interfaces to exchange data with the legacy system. Complexity of external communication can be delegated to Enterprise Service Bus.
Decomposing a monolithic application into Microservice is not always simple because of the complexity of business processes. We can start Microservice adoption with initial focus on only new features that can be planned as Microservice. ACL (Anti-Corruption Layer) pattern can be used here for doing this data transformation with the legacy system.
Entities generally have different concepts in different contexts. Product entity has different meanings in order Microservice and shipping Microservice. Any changes in shipping Microservice should not impact product concept in order Microservice. Having attributes related to shipping domain in product, the Microservice might corrupt the product concept in product Microservices. Context map provides required mapping of attributes from product Microservice to shipping Microservices. Having an anti-corruption layer (ACL) outside Microservice context, probably in gateway service can resolve this issue.
Consistency and Atomicity are often a concern in any distributed application. It is possible to provide eventual consistency using event sourcing and reliable publishing of events. Event driven architecture can be used effectively for achieving eventual consistency. In this architecture, a Microservice publishes a change event when something noteworthy happens, such as when it updates a business entity. Other Microservices subscribe to these change events. A Microservice can update its own business entities when it receives an event, which may lead to more events being published.
Atomic Transaction can be achieved using two-phase commit. However, it is difficult to use two phase commit in poly-got persistence as few Microservices might be using databases which do not support two phase commit. One way to achieve atomicity is by publishing events using local transaction. This can be done using an event table, which works as a message queue, in the database that stores the business entity’s state. A new record is inserted in this table after a business entity commits the changes using local transaction. A discrete application process queries the event table. It publishes the events to the message broker, and then makes use of a local transaction to indicate the events as published.
Pros of Distributed Applications
- Distributed application with Microservices based on architecture has multiple benefits like technology, platform and programming language independence.
- Distributed application with Microservices based on architecture leads to simplified development, deployment and short release cycles.
- Perfect modularity is maintained as Microservices can be independently deployed without any impact on various environments as well as in production.
- Using newer tools like Docker containers and Docker compose, extensive automation can be achieved.
- Many open source offerings are in the market for Microservice development like Spring Boot, Spring Cloud, and Netflix which provide infrastructural services for distributed applications.
Cons of Distributed Applications
- Development or selection of infrastructure services matching your requirement is a challenge.
- Consistency, synchronization and atomicity of the operations are concerns which need to be addressed with dedicated efforts.