Any application designed as a distributed set of components must rely on network connections. Many of today's developers lean toward the REST model of connectivity used on the web. Likewise, most microservices applications developed or used today are based on RESTful APIs. However, REST is not the only way to connect microservices. In some cases, it's not even the best choice.
Making sense of API model types
The APIs used in distributed component applications broadly separate into three categories: synchronous/asynchronous, single-target/multitarget and text/binary. The traditional microservices RESTful API is an example of a synchronous, single-target and text-based relationship. Keep in mind that application requirements must align with these three API model categories.
The most commonly used microservices communication protocols are REST, HTTP, JSON and the Facebook-developed Thrift. However, all three of the API model categories can clash due to their limitations. In addition, as the overall REST model is data-driven, it's presumed that the target microservice is a simple GET-and-POST resource. This works fine for web services, but microservices developers often find themselves limited by the traditional REST model.
The primary motivation to deviate from the REST model is usually the need to transfer binary information. Microsoft's Windows Communication Foundation services employ a RESTful semantic to transfer binary data, and it's also possible to use a simple TCP session for binary exchanges. The problem with the TCP approach is that the developer must create a partner semantic that acknowledges messages and synchronizes the dialogue. To solve this problem, review your client/server or object transfer design patterns, and choose the pattern that best matches the application.
Synchronous protocols, asynchronous protocols and everything in between
Synchronous component relationships can cause problems for microservices if they share an instance, or a load-balanced set of instances, across applications. Since each application runs independently, a call to a shared microservice could interfere with a call from another microservice. Synchronicity is also risky in microservices. If one microservice is blocked, it may then block other microservices' attempts to call it and create an outage.
From a design and architecture perspective, request synchronicity breaks a fundamental part of good microservice design: autonomy. It's presumed that, when synchronous calls block a microservice, it is no longer an open resource. However, when that presumption is untrue, it can lead to confusion and instability.
It's possible to make REST semisynchronous through methods such as HTML polling. The server-push features of HTTP/2 also alleviate issues around binary payloads and can multiplex requests on a single port. Microservices developers who want to keep the HTTP model can settle on HTTP/2, but there are still other options.
In asynchronous microservices communication, a message is sent to one microservice, and it moves along until it requires a response. That response may come in the form of an event or a callback. Asynchronous microservices make connections through some form of a service or message bus. The most popular protocols are Advanced Message Queuing Protocol (AMQP) and Streaming Text Oriented Message Protocol. AMQP supports binary, so it's generally the more flexible option. The Message Queue Telemetry Transport (MQTT) protocol is also asynchronous and is single- or multitarget-capable. However, due to MQTT's limited semantic support and inability to offer queuing, it isn't the best option for microservices.
Asynchronous protocols queue messages for delivery. This eliminates the tight coupling between the sender and receiver that is found in a synchronous operation. This relieves the risk of collisions when multiple applications use microservices. It also facilitates load balancing and enables multitarget distribution of messages. This model also supports the publish-and-subscribe method of information distribution, which is valuable when a variable group of target microservices might need to view a certain message type.
Some approaches to microservices communication are designed for agility. The most notable is gRPC, now widely seen as an alternative to REST for microservices communication. RPC stands for remote procedure call and, in some aspects, is a throwback to old concepts, like Common Object Request Broker Architecture and service-oriented architecture. Don't dismiss it because it seems retro, because it may provide a leading edge in microservices communication.
GRPC provides a way for components to reference microservices as though they're a local procedure instead of a remote one. There are gRPC tools that support both synchronous and asynchronous operation and enable both textual and binary data transferring. Google's Pub/Sub multitarget message service is accessible with gRPC, too.
Match the protocol to the mission
The plethora of microservices communication protocols reflects, in part, a plethora of microservices missions. The options vary in terms of capabilities, overhead and the model of application construction it uses. Application planners and architects need to consider these options when they build new applications or use application modernization strategies to update old applications. If not, there is a risk that different approaches to microservices application design will dictate different protocols and APIs, which makes it tougher to reuse components and microservices.
It's also easy to fall into a trap of software-think. Development groups are responsible for elegant, modern designs that minimize development cost and errors. However, they're also responsible for the utility of their projects. Every microservices communication protocol decision has a potential business impact, so it's critical to make the right choice.