Understanding Microservices Communication and Service Mesh
Learn how the need for better communication between a complex array of services led to the evolution of the service mesh.
Join the DZone community and get the full member experience.Join For Free
Microservices architecture (aka MSA) is reaching a point where handling the complexity of the system has become vital to reap the benefits the very same architecture brings to the table. Implementing microservices is not a big deal given the comprehensive set of frameworks available (like Spring Boot, DropWizard, NodeJs, MSF4J, etc.). The deployment of the microservices also well covered with containerized deployment tools like Docker, Kubernetes, Cloud Foundry, Open Shift, etc.
The real challenge with the microservices type implementation is the inter-microservice communication. Now we have gone back to the age where we had the spaghetti deployment architecture where service to service communication happens in a point to point manner. Enterprise has come a long way from that position through ESB, API Gateways, Edge proxies, etc. Now it is not possible to go back to the same point in the history. This requirement of inter-microservice communication was not an afterthought. The proposed method at the beginning of microservices wave was to use smart endpoints, and dumb pipes.
Developers have used message brokers as the communication channel (dumb pipes) while making the microservice itself a smart endpoint. Even though this concept worked well for initial microservices implementations, with the advancements of the implementations and the scale and the complexity, this concept was no longer enough to handle the inter-microservice communication.
This is where the service mesh concept came into the picture, with a set of features which are required for pragmatic microservices implementations. Service mesh can be considered as the evolution of concepts like ESB, API gateway, and edge proxy from the monolithic SOA world to the microservices world.
Service mesh follows the side car design pattern where each service instance has its own sidecar proxy which handles the communication to other services. Service A does not need to be aware of the network or interconnections with other services. It will only need to know about the existence of the sidecar proxy and do the communication through that.
At a high level, service mesh can be considered as a dedicated software infrastructure for handling inter-microservice communication. The main responsibility of the service mesh is to deliver the requests from service X to service Y in a reliable, secure and timely manner. Functionality wise, this is somewhat similar to the ESB function where it interconnects heterogenous systems for message communication. The difference here is that there is no centralized component rather a distributed network of sidecar proxies.
Service mesh is analogous to the TCP/IP network stack at a functional level. In TCP/IP, the bytes (network packets) are delivered from one computer to another computer via the underlying physical layer which consists of routers, switches, and cables. It has the ability to absorb failures and make sure that messages are delivered properly. Similarly, service mesh delivers requests from one microservice to another microservice on top of the service mesh network which runs on top of an unreliable microservices network.
Even though there are similarities between TCP/IP and service mesh, the latter demands much more functionality within a real enterprise deployment. Given below is a list of functionalities which are expected from a good service mesh implementation:
- Eventually consistent service discovery
- Latency aware load balancing
- Circuit breaking/Retry/Timeout (deadlines)
- Authentication and Authorization (Security)
There can be more features than in the above list, but we can consider any framework a good one if it offers the above list. The above mentioned functionalities are executed at the sidecar proxy where it directly connects with the microservice. This sidecar proxy can live inside the same container or within a separate container.
With the advent of more and more features within the service mesh architecture, it was evident that there should be a mechanism to configure these capabilities through a centralized or common control panel. This is where the concept of a “data plane” and “control plane” comes into the picture.
At a high level, the responsibility of the “data plane” is to make sure that requests are delivered from microservice X to microservice Y in a reliable, secure, and timely manner. So, functionalities like
- Service discovery,
- Health checking,
- Load balancing,
- Security, and
are all parts of the data plane functionality.
Even though the above functionalities are provided within the data plane on the sidecar proxy, the actual configuration of these functionalities is done within the control plane. The control plane takes all the stateless sidecar proxies and turns them into a distributed system. If we correlate the TCP/IP analogy here, the control plane is similar to configuring the switches and routers so that TCP/IP will work properly on top of these switches and routers. In a service mesh, the control plane is responsible for configuring the network of sidecar proxies. Control plane functionalities include configuring
- Load Balancing,
- Circuit Breaker/Retry/Timeout,
- Deployments, and
- Service Discovery.
The following figure explains the functionality of the data plane and control plane well.
Opinions expressed by DZone contributors are their own.