When integrating two independent services you have two options: making a remote procedure call (RPC), or sending a message. Which should you choose?
What is a Remote Procedure Call?
An organization often needs to share data and processes between multiple independent processes in a responsive way. For example, updating a user’s name in a shipping system may trigger updates in a billing system. The shipping system could update the billing system’s data directly by modifying a shared database, but this approach requires the shipping system to know far too much about the internal processes of the billing system. Instead, the business system can encapsulate the update operation behind an interface in the form of a remote procedure call, or RPC.
The RPC applies the software development principle of encapsulation to the integration of entire systems. If one system needs to modify or retrieve some data that is owned by another, it asks that system directly through its interface, allowing each system to maintain the integrity of the data it owns.
The Perils of RPC
Remote procedure calls map nicely with how programmers already work — if you need to do something, make a function call. Unfortunately, this is more of a disadvantage than an advantage in distributed systems; there are big performance and reliability differences between making a remote procedure call over a network and making an in-memory procedure call to a library. Remote calls are slower, and they are much more likely to fail. These essential problems in distributed environments cannot be ignored.
Furthermore, encapsulating the actions of a system behind an RPC interface helps eliminate shared data, but the calls themselves tend to tie the different systems into a growing knot.
What is Messaging?
Asynchronous messaging is fundamentally a solution to the problems of distributed systems: how can we integrate disparate applications in a loosely coupled way? By using messaging, we can transfer packets of data frequently, and asynchronously.
The asynchronous nature of messaging forces developers to form a clearer mental model of distributed systems, which encourages design of components with high cohesion and low coupling. This low coupling allows messages to be transformed in transit, broadcast to multiple receivers, or routed to particular destinations, without the sender or receiver knowing.
This knowledge gap between sender and receiver is an advantage in loosely coupled systems — one of the most difficult aspects of integrating applications is handling communication and coordination between humans, and by removing the “need to know” from the process, messaging works with human nature, rather than against it. This allows each application to keep their own conceptual model of the data being published and consumed, without coordinating with other systems.
The Perils of Messaging
Messaging is a great solution to distributed communication. However, it is not a panacea. First, asynchronous program design is not how most application developers are taught — asynchrony has a learning curve. Asynchronous communication can also make testing and debugging harder. Lastly, although the low coupling between applications is an advantage, it can lead to each application having to write “glue” code to slightly modify messages in ways that fit everything together.
One of the problems with adopting messaging as a programmer is understanding some of the patterns used for communication. All of the patterns described here are available as part of the Messaging Platform and can be used by your application today.
Request-reply uses an asynchronous messaging system to perform a synchronous operation. In a request-reply exchange, the requestor sends a message and waits for a reply on a particular channel. Typically, the reply channel is included as part of the original message so that the receiver knows where to send its reply.
Request-reply provides remote procedure call facilities over an underlying asynchronous messaging platform.
Publish subscribe allows a publisher to broadcast a message to all interested receivers. Publish subscribe is a one-to-many communication where any active subscriber listening on a message channel receives the message.
With point-to-point communication (also known as queueing), the messaging system ensures that only one consumer receives a given message. If the channel has more than one consumer, they become competing consumers and the messaging system ensures that only one consumer receives each message. This design makes consuming messages highly scalable because messages are distributed across multiple consumers running in parallel.
Asynchronous messaging exposes a number of interesting patterns for integrating distributed systems. By knowing and applying these patterns you can pick the best design for your system, keeping your system loosely coupled with others, yet highly reactive to change.