A microservices architecture allows for modularity, scalability and the integration of complex systems -- all very important for a service-based application. But despite its growing popularity and advantages, administrators and system architects face various challenges around handling communication between the various services. That means developers need to play close attention to their microservices messaging patterns.
Let's look at some of the major fundamentals of microservice messaging patterns and the most important aspects of communication to consider.
Loose service coupling
Microservice architecture arranges the application in the form of loosely coupled services that can use protocols, like HTTP, for communication. Loose coupling reduces the dependency between components and enables them to break down into definable elements with particular goals.
Tight coupling, on the other hand, enables components to maintain references to each other and call methods directly. This form of coupling creates increased interdependency, which means that a change in one component will require changes in the others. But tight coupling will typically work well for small applications where it is easy to identify these interdependencies and work within the system.
On the other hand, with a long list of functions and distributed nature of a service-based application, loose coupling is the better option. Loose coupling is highly changeable and leads to greater flexibility, as changes to any individual service can be made without affecting the functioning of other services. Keep in mind, however, that loose coupling requires developers and app managers to implement strong monitoring and service discovery to track the flow of messages across the architecture.
A major obstacle encountered with microservices-based architectures is determining the scope and method of communication between services. Typically, there are two basic options: synchronous communication and asynchronous communication.
Synchronous communication works well within a monolithic architecture because of its simple, two-way messaging path -- the consumer sends a request to the server, and the server sends a response. This makes it easy to track the transfer of messages since there is a relatively small number of messaging transactions, and it is very direct since messages flow back and forth through one single channel.
However, with microservices, multiple communication pathways function simultaneously to ensure top-notch user experience. In these scenarios, synchronous communication can be redundant, slow and unresponsive. Asynchronous communication enables independent functioning of consumer and product services. The communication thread is not blocked by any single service waiting for a response, since the communication system can handle other calls in the meantime, and two or more threads can execute at the same time.
Asynchronous communication also enables one-to-many communication, often through a system like an API gateway, where the consumer service can send requests to multiple product services at once. Unlike a traditional enterprise service bus, an API gateway is decentralized, and it's purpose-built to support asynchronous communication between services.
Lightweight message brokers
Traditionally, client-server apps use request-based communication patterns to interact internally. However, microservice messaging patterns need to focus on a message-based system that doesn't need to handle requests in a first-come, first-served order, and won't cause a requesting service to crash if it doesn't receive a response.
In other words, the requester shouldn't always need to receive a reply from the responding service after sending a request. Instead, it should have the means to access any data it needs to still run while it waits for the new response. This will allow the transfer of bulk data between communicating systems in parallel sessions. This pattern is based on the famous dumb pipes and smart endpoints approach, which focuses on using a lightweight message broker. Here are some popular brokers designed for microservice messaging patterns:
- Amazon Simple Notification Service. This is a fully managed messaging service that enables microservices decoupling and works with distributed systems, as well as serverless applications. It is particularly useful for publisher systems to send out messages to a large number of subscribers with its parallel processing features.
- RabbitMQ. This is an open source message broker that is easy to deploy and cloud-enabled. It can cater to large scale and high availability requirements with its multiple messaging protocols.
- gRPC. This is another open source framework that connects services across data centers and enables applications to work across languages and platforms. It is well-known for its load balancing, tracing, health checking and authentication features, along with its ability in distributed computing.