Killer Apps of Message Queues

Killer Apps of Message Queues

Message queues are an asynchronous inter-process communication protocol that gains much of its glory with the recent hypes in microservices. Senders and receivers do not interact with the middleware at the same time, so message queues are a great way of decoupling communication from business logic since upstream services may talk to the middleware only and not with any other services.

MQs are not a panacea. It introduces additional components to the system and thus new challenges in availability and reliability. The extra roundtrip to downstream receivers means extra delay. The rule of thumb would be whenever synchronous invocation makes more sense, do RPC and not MQ. Let’s focus on the killer applications of MQ in the following text.

Buffering Traffic Spikes to Downstream Services

One downside of RPC framework is that the downstream services/callees have no flow control. If the downstream service demand is much higher than upstream request rates, especially so when downstream handles complex business logic with atomic, durable operations, then essentially the downstream is DOS-ed and that service is gone. Common solutions include upstream queuing to limit request rate or downstream queuing to limit execution rate, yet both introduces unnecessary complexity to the service code.

With MQ, flow control could be easily achieved with downstream pulling from MQ-middleware at its own rate that matches its service demand, which may be further optimized with batch-writes or asynchronous durable writes.

Pub/Sub to remove reverse dependency

Imagine a user makes a new post on a forum, which is going to reward the user with some points, update the user personal stats, push to other user feeds, etc. It seems an invocation relationship between upstream and downstream services, but the upstream hardly cares about the results of downstream execution and just want to make sure things eventually get executed. Using RPCs puts reverse dependency into upstream because whenever a new set of logic or a new service was added to the list of callees, developers have to change the upstream service code, build, and deploy. Downstream service outage also affects upstream availability.

Using MQ, new downstream service could subscribe to the upstream and thus no code change to the upstream. The upstream also no longer needs to wait for all downstreams to reply, reduces service demand, and returns success once MQ says the message is committed.

Higher throughputs in long, synchronous tasks

There are also times when the upstream cares about the results but execution takes a while (for example third-party service call through public network, such as requests to PayPal payment). The upstream may call the API directly and receive an acknowledgment. After the transaction is processed, Paypal invokes a callback to a uniform gateway of ours, which pushes to MQ. The upstream subscribes to such messages and gets results eventually.