Microservices, APIs and Integration
I’ve been writing/speaking on the topics related to Microservices for a quite a sometime. Although many people now understand the fundamentals of microservices architecture, still there’s a quite a lot of confusion when it comes to the application of Microservices with API and Integration technologies.
From Monolithic Applications to Microservices
Let’s start our discussion with how the enterprise architecture has evolved from monolithic applications to microservices.
Monolithic Applications
When it comes to building a software solution to solve various business requirements, we’ve used(pre-SOA era) to build monolithic applications on top of various systems such as databases, file storages etc.(System of Records).
These applications are designed to facilitate numerous business requirements. Hence, a given software application offers hundreds of functions and all such functions are generally piled into a single monolithic runtime (e.g. ERP, CRM etc.). When it comes to inter-application communication, these applications use proprietary point to point style communication style(or connected with EAI solutions).
Obviously this architecture has inherent limitations.The deployment, troubleshooting, scaling, and upgrading of applications was a nightmare and also point-to-point style communication nor having bulky EAI to connect these applications were not scalable.
SOA and ESB
Service-oriented architecture (SOA) is designed to overcome the problems resulting from monolithic applications by introducing the concept of a ‘service’. Each business functionality is built as a (coarse-grained) service(often implemented as Web Services)with several sub-functionalities and they are deployed in an application server which is a monolithic runtime. When it comes to consumption of business functionalities, often we need to integrate/plumb multiple services and other systems and consumers consume the virtual/composite services exposed from ESB layer. Hence ESB is used as the centralized bus that connects all these services and systems.
In this architecture, ESB layer comprises of various functionalities such as message routing, transformation, service orchestration and capabilities to implement various EIPs. Therefore, a significant portion of business logic is residing in ESB layer and it is developed, deployed and scales as a single monolithic runtime.
API Management
Exposing business functionalities as managed services/APIs has become a key aspect of the modern enterprise architecture. However, web services/SOA is not really the ideal solution to cater to such requirements due to the complexity of the Web Service related technologies such as SOAP, WS-Security, WSDLs etc. and the lack of features to build an eco-system around APIs(self-servicing etc.).
Therefore, the most organization puts a new API Management/API Gateway layer on top of the existing SOA implementations. This layer is known as the API façade, in which exposes a simple API for a given business functionality and hide all the internal complexities of ESB/Web Services layer.
Microservices
Microservices architecture has emerged as a better architecture paradigm to overcome the drawbacks of the ESB/SOA approach. The monolithic nature of ESB and service hosting runtimes is the main hurdle when it comes to the agile development of services (such as running inside containers).
Hence, microservices architecture (MSA) encourages to develop a single application as a suite of small and independent services that are running in their own process, developed and deployed independently.
Also, Microservices architecture encourages to not to have a centralized ESB and disperse the logic that was residing in ESB into services (smart endpoints and dumb pipes) So, what that means is to demolish the ESB and application server layers into microservices and made them accessible through API Manager/Gateway.
Where is ESB/Integration?
If we completely remove ESB in Microservices architecture, where do we implement all sorts of functionalities that were offered from ESB such as message routing, creating service compositions/chaining, protocol and message format transformations, resiliency patterns and various other EIPs? This is one of the most common question and confusion that most of the people from enterprise integration domain have.
Many organizations who adopted micorservices architecture, initially tried to build their applications by building fine-grained microservices and plumbing them with point-to-point style communication. They pretty much use the same type of technology to build all these services (Java, Node etc.)
And even some implementations had the API Gateway as the main component that takes care of various service compositions and orchestrations. As these microservice implementations getting matured, they start realizing that treating all microservices the same is not the most effective approach and they can’t simply ignore the ESB capabilities or API Gateway capabilities that we had in previous architectures. And trying to build such capabilities using generic microservice development framework is a nightmare. Above all, they find that the most complex challenge in realizing microservice architecture is not building the services themselves, but the communication between services.
The most complex challenge in realizing microservice architecture is not building the services themselves, but the communication between services.
Although some ESB vendors try to exploit the same to resurrect the ESB in the microservices architecture, owing to its fundamental incompatibilities, ESB won’t be able to fit into the Microservices by any means.
Microservices Layered Architecture
It is important to understand that, the tasks that an ESB does in an ESB based SOA implementation, don’t simply disappear when you switch to Microservices Architecture. Rather, all ESB/integration functionalities are segregated and dispersed among all the microservices.
So, if we have a closer look at the microservices implementation, we can identify different types of services that we can categorize into few different layers. We can come up with a layered architecture as shown in figure 4 ( I originally proposed as a logical set of layers, but this could well be a concrete layered architecture too) with different microservices types.
So, based on service functionalities and granularities, we can identify following service categories.
1. Core/Atomic Micoservices
At the bottom layer, we have fine-grained self-contained services (no external service dependencies) that mostly comprise of the business logic and less or no network communication logic.
2. Composite/Integration Microservices
Atomic microservices are often cannot be directly mapped to a business functionality as they are too fine-grained. Hence a specific business functionality may require a composition of multiple atomic/core services. The middle layer comprises of such composite or integration microservices. These services often have to support a significant portion of ESB functionalities such as routing, transformations, orchestration, resiliency and stability patterns etc.
Composite/integration services are coarse-grained(relative to atomic services), independent from each other and contains business logic(routing, what services to call, how to do data type mapping etc.) and network communication logic(inter-service communication through various protocols, resiliency behaviors such as circuit breakers).
Most of the ESB/integration capabilities(such as EIPs, resiliency and stability patterns) are realized in Microservices architecture at the composite/integration services layer.
These services also could bridge the other legacy and proprietary systems(e.g SAP ERP), external web APIs (e.g. Salesforce), shared databases etc. (often known as the anti-corruption layer).
3. API Services/Edge Services
You will expose a selected set of your composite services or even some atomic service as managed APIs using API services/Edge services.These services are a special type of composite services, that apply basic routing capabilities, versioning of APIs, API security patterns, throttling, apply monetization, create api compositions etc.
Technologies for building Microservices
When it comes to implementation of microservices, most of the current microservices implementation arbitrary use a given framework or a programming language to build microservices without taking the different service types into the account. With the proliferation of the number of services, this will lead to design, implementation and scalability nightmares. Therefore, we need to pick the right technology, based on the nature of the microservices that we are developing.
Core/Atomic Services: Most of the existing technologies are focusing on building these services. There are numerous of frameworks/libraries available for build this type of services (e.g. SpringBoot, Dropwizard, WSO2 MSF4J)
Composite/Integration Services: Most of the current microservice implementations tried to use the same set of technologies to build both core/atomic services and composite/integration services. However, most of the microservices frameworks and platforms are not designed for building composite services.
Therefore building composite services is becoming the most challenging task(just imagine the amount of work related to implementing various integration patterns from scratch, using Java or any other similar programming language) in realizing microservices architecture.
To overcome this problem There are emerging technologies such as Ballerina (which is a programming language designed for service compositions and network interactions), and Service Mesh frameworks (With ‘Service Mesh’ you can offload the network communications to the service mesh and we can only focus on Business logic. E.g. you don’t need to worry about circuit breaking when you call another service).
API/edge Services: Most of the existing (monolithic) API Management and gateway solutions can facilitate these service, as long as API services contain minimal business logic. However, most microservice implementations try to put a massive amount of business logic into this layer, while keeping it as a single monolith. That’s not a sustainable architecture and it violates the key principle of Microservice. So, there are two possible approaches to overcome this problem.
- Offload the compositions to composition layer and can use a monolithic gateway for just exposing them as APIs.
- Segregate API Gateway runtime(micro-gateway concept) so that each API/edge service can be built and manage independently.
The same technologies that we use to build composite service can also be used in API/edge service development. So, most of the existing (monolithic) API Management/Gateway solutions are still evolving to support concepts such as micro-gateways.
Conclusion
Hope this post was helpful to clear up some of the doubts you had related to to practical usage of microservices, APIs and integration. We can summarize the key takeaways from this post as follows:
- The layered microservices architecture that is discussed in this post is quite powerful to address the different aspect of service implementation.
- Integration never disappears! Rather it’s morphing into different forms of implementation (point-to-point -> ESB -> composite services).
- The traditional ESB/integration capabilities have dispersed into composite microservices layer and externally consumable services are exposed through API Management layer.
- We need to select the appropriate technology set for each microservices category.
I’m also planning to write on some of these topics in-detail. Stay tuned!