The Microservice Pattern
The Microservice Pattern
Before we get into the Microservice Pattern, let us understand what “Microservice” is all about. Microservices are a more concrete and modern interpretation of service-oriented architectures (SOA) used to build distributed software systems. Like in SOA, services in a microservice architecture are processes that communicate with each other over the network in order to fulfill a goal.
The idea behind microservices is that some types of applications become easier to build and maintain when they are broken down into smaller, compostable pieces which work together. Each component is developed separately, and the application is then simply the sum of its constituent components. This is in contrast to a traditional, “monolithic” application which is all developed all in one piece. When the different components of an application are separated, they can be developed concurrently. Another is resilience. Rather than relying upon a single virtual or physical machine, components can be spread around multiple severs or even multiple data centers. If a component dies, you spin up another, and the rest of the application can continue to function. It allows more efficient scaling, as 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.
Problem Services and other components of a solution are packaged together in a monolithic deployment bundle. Deploying a new version of the service can require redeploying the entire solution. Also, there is less flexibility to configure service-specific scalability, availability, persistence, monitoring, and security logic.
Solution Each service should be treated as a separate independent product, component and deployed independently from packaged application. Such a service which is independent and treated as a separate product is further qualified as a “Microservice”
Principle Service loose coupling, Service Autonomy
- Service Loose Coupling: in order to ensure that Service Contracts are not tightly coupled to the service consumers and to the underlying service logic and implementation
- Service Autonomy: Service exercise a high level of control over their underlying runtime execution environment
Problem Statement without Microservice architecture discipline, an application for which a service is developed will typically be comprised of all other services along with other additional components, artifacts. A common and practical approach to the implementation of such an application is for its collective artifacts (including the service logic source code and technical interface artifacts) to be stored in a source code repository. In this case, services are commonly packaged and deployed together with any additional required artifacts, resulting in a “monolithic” deployment bundle (Figure 1).
Even when a service is designed in accordance with service-orientation design principles, the fact that it is bundled as part of a monolithic application deployment creates a usually undesirable requirement to build, package, and redeploy the entire application bundle whenever a new version of that service needs to be released. Further, the ability to improve the scalability of specific services using clusters, grids, or cloud-based IT resources is limited because such scalability mechanisms may only be applicable to the entire deployed application. Likewise, the runtime environment may not support service-specific security, persistence, and monitoring configurations. Additionally, faults, such as a memory or resource leaks, in one of the application artifacts could potentially bring down services in the same deployment bundle. Finally, services within a single monolithic deployment bundle may need to be developed using the same development language and frameworks as other application artifacts.
Solution Treat each service as a unique product that it is developed independently from other services and application artifacts. Such services are excluded from the monolithic application deployments and are instead packaged and deployed independently (Figure 2).
Note that this pattern may not be suitable for all services. The following criteria can help with the identification of microservice candidates:
- Services to which the Service Autonomy principle can be applied to a significant extent.
- Services that do not need to participate in distributed transactions.
- Services that do not need to be part of multiple complex service compositions.
- Services with a small or limited functional scope.
- Services that do not rely on service capabilities that use synchronous request-response calls.
- Services those are easy to deploy and monitor. (This criterion favors the use of implementation technologies that do not require multiple configuration and technical interface artifacts and that do not require sophisticated runtime support for message transformation, reliable communication, transaction management, and other activity management.)
- Services that are not implemented as platform-specific components. (The use of proprietary component technologies can result in negative coupling that can complicate deployment of stub modules on the service consumer side.)
- Services to which the Utility Abstraction or the Entity Abstraction patterns have been applied.
There can be variations on both the basic monolithic approach depicted in Figure 1 and the microservices approach shown in Figure 2. For example, Figure 3 illustrates an architecture that is still somewhat monolithic but also one step further toward a microservice model. In this case, the collective deployment of the services could be based on their underlying technology. Separate deployment bundles could be created for REST services, SOAP services or perhaps cloud-based services.
Impacts The application of the Microservice pattern can improve the agility at which new versions of services are released due to a resulting decrease in build+test+deploy cycles. These improvements can lead to a continuous delivery practice for services. On the other hand, the overall deployment can become more complex due to the potential involvement of multiple jobs, scripts, file transfer areas, and configuration files required for publication. Organizations with a strong DevOps practice will more easily overcome such challenges. Rolling out a new version of a microservice generally imposes minimal downtime. The reliability of the entire solution can be improved because any possible microservice runtime fault will affect only that microservice and its service consumers. Each microservice can be independently configured with respect to replication, security, persistence, and monitoring. There is further an increase in design-time autonomy that allows individual microservices to be designed and implemented using different frameworks and development languages, when necessary. Microservices can have a negative impact on performance because they need to communicate over the network. To avoid chatty communications and performance issues, microservices are ideally designed with coarse-grained service capabilities. A solution based on microservices also requires a larger memory footprint because several classes and libraries are often replicated in each microservice bundle. The runtime dependencies of a microservice need to be carefully designed to avoid jeopardizing its service autonomy. For example, Microservices should not participate in atomic distributed transactions.
Make Sure you give this post 50 claps with a follow if you have really enjoyed this post and want to see more such posts.