I have a Microservices Architecture. To send information from one to another, I will use a REST communication.
Don’t!
The default option is using REST communication between the internal Microservices. But sometimes, there are other approaches that fit better to my needs.
REST
![](https://sergiolema.dev/wp-content/uploads/2023/11/rest-edited.png)
The REST approach is easy to implement. The first reaction will be to use it.
The REST requests are based on the following:
- The endpoint/URL describes the resources and sometimes the action;
- More details about the action can be find in the HTTP verb;
- And the details of the resources are in the body.
Let’s see some examples:
- GET /vehicles/123: from all the available vehicles, I read the one with the ID 123;
- GET /vehicles: from all the available vehicles, I read them all without any filter;
- POST /vehicles (with a JSON body): I add a new vehicle item;
- PUT /vehicles/123 (with a JSON body): from all the available vehicles, I update/replace a single one with the ID 123;
- POST /vehicles/search (with a JSON body): from all the available vehicles, I perform a search with the criteria present in the body;
- and so on.
The REST communication protocol is made with in JSON format (if it includes a body) and is synchronous. This means that the URL and body and human readable. This will ease the task of debugging.
SOAP
![](https://sergiolema.dev/wp-content/uploads/2023/11/soap-edited.png)
This is an older protocol. but still widely used.
Instead of using JSON format as in the REST communication, we use XML which is more verbose.
Let’s see the structure of a soap request:
- The endpoint/URL has no information about the resource neither the action. The application use to have a single endpoint or few of them;
- Only the POST HTTP verb is used, as each request needs to send a body;
- All the information about the action and the resources are present in the body;
- The body must have a given structure by a WSDL file (defined in the header of the XML).
Let’s see some examples, all done to the endpoint POST /app/do:
- This one reads from the resource type vehicle the one which has an ID equal to 123;
<app>
<action>read</action>
<resource>
<type>vehicle</type>
<id>123</id>
</resource>
</app>
- This one reads from the resource type vehicle all the items without any filter;
<app>
<action>read</action>
<resource>
<type>vehicle</type>
</resource>
</app>
- This creates a new item of type vehicle with the fields indicated;
<app>
<action>create</action>
<resource>
<type>vehicle</type>
<vehicle>
<brand>Ford</brand>
...
</vehicle>
</resource>
</app>
- This replaces the resource type vehicle with all the given fields;
<app>
<action>replace</action>
<resource>
<type>vehicle</type>
<vehicle>
<brand>Ford</brand>
...
</vehicle>
</resource>
</app>
- This searches all the items of type vehicle and criteria brand…
<app>
<action>search</action>
<resource>
<type>vehicle</type>
<criteria>
<brand>Ford</brand>
...
</criteria>
</resource>
</app>
As with REST, the communication is synchronous. And having the body in XML format makes the debugging task more verbose but manageable.
RPC
![](https://sergiolema.dev/wp-content/uploads/2023/11/rpc-edited.png)
REST communication is compact. On the other side, SOAP is very verbose. Then comes RPC (Remote Procedure Call) which is in binary format. Very compact, which means faster.
Using RPC is like calling a method from another microservice. A layer will be responsible to serialize the input parameters to the target microservice and deserialize the received response at the end.
Still it’s a fast protocol, I must ensure that all the input parameters and output values are serializable.
The disadvantages here are the difficulty to debug. I can’t send a binary request with Postman.
Messages or Queues
![](https://sergiolema.dev/wp-content/uploads/2023/11/messages-edited.png)
This kind of communication is asynchronous. The sender is responsible to append a message to a queue, and the receiver will read (when available) the messages from the queue.
This breaks the hard link between the sender and the receiver. I can now send a message even if the receiver isn’t available.
With this strategy, I need a message broker, a server which handles the reception and delivery of all the messages. It can be AWS SQS, RabbitMQ, Kafka or other.
A difficulty with this strategy, is at the rollout. What if the new version changes the messages structure? The messages which are still present in the queue can’t be edited to have the new format.
Database
![](https://sergiolema.dev/wp-content/uploads/2023/11/database-1-edited.png)
Similar to the messages in a queue, I can append actions to a table in the database. Those actions will be read in asynchronous by a consumer. This is exactly the same use case as the messages in the queues.
But with the rollouts, it’s easier to adapt the existing rows.
On the other side, to read the rows, I need a single reader with a cron job.
What if I have many readers? They may overlap reading the same row.
Advantages & Disadvantages
Here is a small table with the main features of each communication protocol.
I hope this helps you to make the adequate choice.
Protocol | Main Feature | Secondary Feature | More |
---|---|---|---|
REST | Easy | Fast | Widely used |
SOAP | Verbose | Widely used | |
RPC | Faster | Hard to implement | |
Messages | Asynchronous | Difficult at migrations | |
Database | Asynchronous | Needs a cron job |
For me, the best communication protocol: use the most adequate for each single microservice.
In the architecture of the project I’m working on, I use several communications protocols depending on each context.
Leave a comment