You may say how much more should we discuss the same thing? True, anyone can get tired of repeating the one description over and over again. So, today, we decided to dive a little deeper and explore the services from a more technical side, but still in a simple way. How do they work? Communicate? Interact? Let’s focus on microservices’ communication and relationships with each other.
Services Themselves. At the Scale
As you remember, after you separated your app into subdomains, each of them is then wrapped into the service package. All of them are deployed and ran entirely independently. We also know that these services usually greatly vary in terms of functionality and development requirements, but their end goal is to communicate with each other after release. Simply put, the microservices ecosystem is about services having some kinds of relationships that result in processing all the client’s side requests correctly.
1. Breaking Communication Barriers
When the services of your app’s subdomains reach out to each other, they use particular inter-process communication protocols, Application Programming Interfaces (APIs), and a specific communication style. The two most common communication protocols in microservices architecture are Remote Procedure Invocation (RPI) and Messaging. What’s what?
- RPI (also known as Remote Procedure Call) – is the simplest inter-service communication protocol for distributed, client-server systems. You might have encountered or even used the examples of RPI technologies before – SOAP, REST, gRPC.
This technique utilizes the request-reply concept – the client/service makes requests to a particular service, and this service has to reply back. Take the shipment app we’ve previously divided into subdomains. Here, the order processing microservice calls the admin subdomain to assign the worker responsible for delivery.
These requests can be both:
- Synchronous – the caller halts until the reply comes back
- Asynchronous – some service invocates the caller with the request for an action that can be performed in parallel while waiting for a response.
One drawback of this approach is that the client has to discover the service instances’ coordinates. Also, both the client and the microservice have to be free of other synchronous calls during their direct interaction, which reduces their availability for other communication requests.
- Messaging – is an asynchronous, more complex inter-service communication protocol. The examples of message tools include Apache Kafka and RabbitMQ.
A self-explanatory term since it means that services exchange messages using a certain broker/channel as an interlink. In detail, to interact with each other, services send their messages to the broker (see the picture). All microservices (subdomains) interested in communicating with these calling services subscribe to the broker to receive the messages. Upon receiving the info encoded in the messages, the services update their own state.
This approach results in such benefits as:
- Asynchronous messages support the principle of the loosely-coupled structure of microservices.
- They improve the availability of services as the broker/channel layer queued up the messages until the receiver is ready to handle them.
- Messaging protocol supports various communication patterns: request-reply, request-synchronous response, publish-subscribe, publish-asynchronous response, notifications, and more.
However, both protocols oblige you to establish the data format that is going to be used for the exchange procedure. Considering the needs of your app’s overall architecture, the data can be transferred as the text or binary sequence (e.g., gRPC protocol). The most commonly used text formats that you might have heard about are JSON, XML, and YAML. These formats are pretty easy-to-implement and debug, but most importantly, they are human-readable. In contrast, while the binary messages are more compact, they are machine-readable and far more difficult to handle.
2. APIs and Contracts. Just business!
Okay, now you probably wonder how exactly each engineering team invokes some external microservices? Well, earlier, we’ve mentioned the API’s role in the communication process. Here we also add another player – the contracts. Just as any business deal, a call, in our case, is sealed with a contract. Such a contract allows the microservices to expose the full set of API’s functions.
For instance, your app’s order processing microservice simultaneously uses two APIs – one for creating new shipment orders, the other one for following the existing orders till they’re successfully delivered. So, how the other system’s services know what is being used and how to invocate it? The microservice issues a certain contract into the system. The other microservices will receive it when needed, read it, and establish a process of remote API’s invocation.
In any case, you have to develop your API according to the architecture style you’re using:
- For SOAP architecture, you need Web Services Description Language (WSDL) – an XML-based interface language that describes the functionality of a web service.
- For REST, there is Swagger that describes the API’s structure in a way for machines to read them.
- gRPC, by default, utilizes the Interface Definition Language that describes the service interface and the payload messages’ structure.
Summing It Up
The modern market dictates its own rules, which require to take into account both the wide range of digital devices and network constraints. To gadgets with bigger memory slots that have a stable and secure internet connection, you can send a detailed response with some additional info attached. But if some smartphone stuck in the middle of nowhere with poor internet connection calls the same API, you might want to cut the size of response data in half, at least. Therefore, each device has different capabilities, so you have to build separate APIs with different contracts per each gadget supported by your app.
Need more explanations? Reach out to our tech experts, we’re always happy to help!