When you work with microservice-oriented applications you must deal with a lot of communication between microservices. There are three ways to setup the communication:
- Synchronous, in which it happens in real time; and
- Asynchronous, in which it happens independent of time; and
- hybrid, which supports both.
Asynchronous operation is extremely useful for environments in which a service, such as a loan processor, can take a long time to process a client request.
The most common type of synchronous communication is HTTP request, in this model one microservice sends a request to another microservice and way for the response.
Although REST proved to be much easier to implement than other comms (notably the XML-based SOAP), it has an inherent disadvantage in that it is synchronous in nature, rather than asynchronous. It is synchronous because it blocks the interaction while it waits for the response.
Examples of synchronous communication are phone calls or video meetings. Asynchronous communication happens when information can be exchanged independent of time. It doesn’t require the recipient’s immediate attention, allowing them to respond to the message at their convenience.
In this model the microservice does not wait for a response, it will send the data to another microservice and continue working independently of the result of that interaction (not blocking it).
This type of interaction is done by the usage of a message broker technology, such as RabbitMQ, Azure Service Bus or Kafka. Once a microservice publish a message to a queue or topic the subscribers will receive the message and process it.
It`s common to use both, synchronous and asynchronous models in the same solution, each type of communication will solve different types of problems.
Transactions And Microservices
When you choose to implement microservices dealing with transactions is a big challenge, rather than monolithic applications where you can use database transactions. In this case you must carefully design how transactions will be handled, there are some strategies and patterns designed to handle it, such as the SAGA pattern.
More Architectural Considerations
If your experience is mainly with enterprise applications, working with a system of microservices will require a change in the way you think about communication. The WAR and JAR monolithic deployments of the past allowed you to make assumptions about the availability of objects. In most cases, you were able to treat requests and responses as if they were simply local method invocations. While simple, this pattern obscures the network and pretends that it is reliable.
In distributed systems, you have no assurances that the service you want to invoke will be running, whether a network issue will prevent your request from arriving, or whether the response will ever come. The inherent dynamic nature of distributed systems makes it important to deal with communication failures as normal occurrences. That’s why it makes sense to use messages and realize how they differ from remote method invocation.
Messaging does not need to be point-to-point. Use of messaging can, and often does, mean adopting an event-driven architecture, which can bring additional benefits. Event-driven systems promote autonomy and decoupling, allowing the development organization and the resulting system to scale more easily. They provide good options for managing consistency and persistence.