Introduction to Asynchronous Processing and Message Queues

Introduction

In a client-server architecture, the client can request a job to be done from the server by sending messages between each other.

Handling this communication can increase in complexity when you begin to manage the rate at which messages are sent, the number of requests a server can handle, or the response time which the client demands.

In this blog, we'll see one way to handle this intricacy.

What is Synchronous Processing?

In synchronous processing, a client sends a request to the server and waits for the server to complete its job and send back the response before the client can resume doing any other work.

This process is often referred to as a blocking request as the client gets blocked from doing any other work until a response is received.

image.png

What is Asynchronous Processing?

Asynchronous processing is the exact opposite of synchronous processing. Here, the client doesn't wait for a response after sending a request to the server and continues doing any other work.

This process is referred to as a non-blocking request as the execution thread of the client is not blocked. This allows systems to scale as more work can be done in a given amount of time.

Synchronous vs Asynchronous Processing

image.png

What are Message Queues?

A message queue is a component that buffers requests from one service and broadcasts asynchronously to another service.

Here, clients are the message producers, who send request messages to the queue instead of any server. They get an acknowledgment when the message is added to the queue, which enables them to continue with their other jobs without having to wait for the server.

Servers are known as message consumers and are served these messages from the queue based on the number of requests they can serve at any given time. This continues until all the messages in the queue have been served.

The two most common messaging queues are — RabbitMQ and Kafka.

Structure of Message Queues

A message queue is primarily a broker of messages between message producers and message consumers.

Each distinct entity in the messaging queue setup (producers, consumers, and queue) has a responsibility and they're decoupled from each other as much as possible.

The only contract between all entities is the messages for which the message queue facilitates the movement from producers to consumers.

In the following sections, we will discuss the responsibilities of each component and look at the various modes with which the message queue delivers a message to consumers.

Message Producers

Message producers initiate the asynchronous processing request. Producers have a responsibility to generate a valid message and publish it to the message queue. Messages submitted to the queue are then queued up and delivered to consumers to be processed asynchronously.

Producers communicate with message queues using the Advanced Message Queuing Protocol (AMQP).

Message Brokers

A message broker is simply just a queue. You can even implement a simple broker programmatically that buffers messages and sends them to consumers as and when needed.

Message brokers are the actual decoupling elements in the setup, sitting between and managing the process of communication between producers and consumers.

Because of their simplicity, brokers are optimized for high concurrency and throughput.

It is important to note that adding message brokers introduces an extra layer of complexity into your infrastructure and requires you to scale them as well. Brokers also have specific requirements and limitations when it comes to scalability.

Message Consumers

The main responsibility of consumers is to receive and process messages from the queue.

Most consumers are API services that perform that actual asynchronous processing.

Consumers can be implemented in different application languages or technologies and maintained independently from other components.

To achieve decoupling, consumers should know nothing about the producers. The only contract that should exist between the two is valid messages from the queue.

When properly decoupled, consumers can serve as independent service layers that can be used by both the message queue setup and other components in your infrastructure.

Consumer Communication Strategies

Message queues need to transmit messages down to consumers, depending on how application developers implement consumers, message queues have three distinct ways of delivering messages to the consumers:

In this model, the consumer periodically checks the status of the queue. This is done at a scheduled interval programmed on the side of the consumer.

If there are messages found in the queue, the consumer picks them up until there are no more messages left to process, or when the 'N' number of messages has been consumed. This 'N' can be configured on the message broker.

Once a message is added, the consumer is notified and the message is then pushed down to it. Messages are pushed down to consumers at a rate at which the consumer can easily regulate.

In this model, consumers can subscribe to a topic. This publisher publishes a message to a topic rather than a queue. Each consumer connected to the broker maintains its private queue to receive messages from topics.

After the consumers subscribe to the topics and when a message is published to that topic, the message is cloned for each subscriber and added to the consumer’s private queue.

Comparing Different Message Brokers

As we have seen above, for asynchronous communication we usually need a message broker.

Below are the few considerations you have to look at when choosing a broker for managing your asynchronous operations:

RabbitMQ

RabbitMQ supports all major languages, including Python, Java, .NET, PHP, Ruby, JavaScript, Go, Swift, and more.

Kafka

Kafka has managed SaaS on both Azure and AWS. Kafka also supports all major languages, including Python, Java, C/C++, Clojure, .NET, PHP, Ruby, JavaScript, Go, Swift, and more.

Redis

Redis is a bit different from the other message brokers. Redis is an in-memory data store. Originally, Redis only supported one-to-one communication with consumers. However, since Redis 5.0 introduced the pub-sub, you can have one-to-many as another option.

Conclusion

In this blog, we covered how asynchronous processing is advantageous over its counterparts and how a message queue helps us achieve asynchronous processing along with keeping the different entities in its setup decoupled from each other.

We also covered some basic characteristics of the most commonly used message brokers: Redis, Kafka, and RabbitMQ.

Here's a bit more detailed instruction for selecting the right message broker to use according to different use cases:

Short-lived Messages: Redis

Large Amounts of Data: Kafka

Complex Routing: RabbitMQ

Happy coding! 💻

(If you find any doubts, updates, or corrections to improve this article, Feel free to share them in the comments) 😊

Starting out in web development?? 💻

Checkout ▶ HTML To React: The Ultimate Guide

This ebook is a comprehensive guide that teaches you everything you need to know to be a web developer through a ton of easy-to-understand examples and proven roadmaps

It contains 👇

✅ Straight to the point explanations

✅ Simple code examples

✅ 50+ Interesting project ideas

✅ 3 Checklists of secret resources

✅ A Bonus Interview prep

You can even check out a free sample from this book

and here's the link with 60% off on the original price on the complete book set ⬇

eBook.png