Dev Learning Lab

The labs on this site need JavaScript to run. The same content is written out below.

Learn › Architecture and operations › Messaging and asynchronous processing

Message queue basics

Leave a note instead of calling directly

When an order comes in, you must send a confirmation email. The order server can call the email server directly and wait until it finishes, or it can put a message that says "send the email" in a queue and respond right away.

Conceptual model · A conceptual model (not checked against a real message queue)

Concepts in this lab

Message queue
An intermediate store that sits between the sending side (the producer) and the receiving side (the consumer), holds messages, and then delivers them. The producer puts a message in and moves straight on to its next work, and the consumer takes messages out and processes them at its own pace. The two systems do not call each other directly, so coupling is lower, and a sudden burst of requests can be piled up and processed later.
Synchronous and asynchronous
Synchronous means that the side that requests a task waits until it receives the result and only then moves on. Asynchronous means that the requester starts the task and moves on to the next work without waiting for the result, and the result is delivered later through a callback, a Future, or a similar means.
Pub/Sub
A messaging approach in which a publisher sends a message to a specific topic (channel) and every subscriber that is subscribed to that topic receives the message. Publishers and subscribers do not need to know each other. The Redis version does not store messages, so a subscriber that is not connected at that moment does not receive the message.
Message delivery guarantees
The level of guarantee about how many times a message is delivered. With at-most-once, a message is delivered at most one time, so there are no duplicates but messages can be lost. With at-least-once, a message is delivered at least one time, so nothing is lost but duplicates can occur. With exactly-once, a message is delivered exactly one time. In practice, systems often use at-least-once and make the consumer handle duplicates (idempotent).
Eventual consistency
The guarantee that, although some nodes may show the old value right after data changes, all nodes end up with the same value over time if no further changes are made. It gives up immediate consistency and gains availability and scalability in return. It is commonly adopted in distributed databases and for synchronizing data between microservices.

Try these

Running with the default settings

  1. 3 orders arrive one after another. Saving an order to the database takes 0.05s, and sending one confirmation email takes 1s.
  2. Order 1: After saving (0.05s), the order server calls the email server and waits until it finishes (1s). The user gets a response only after 1.05s.
  3. Order 2: After saving (0.05s), the order server calls the email server and waits until it finishes (1s). The user gets a response only after 1.05s.
  4. Order 3: After saving (0.05s), the order server calls the email server and waits until it finishes (1s). The user gets a response only after 1.05s.

Result of this run

Code

@PostMapping("/orders")
OrderDto order(@RequestBody OrderRequest req) {
    Order order = orderService.save(req);          // 0.05s
    mailClient.sendConfirm(order);                 // calls the email server directly and waits
    return OrderDto.of(order);                     // responds only after the email is done
}

Assumptions of this model

This is a model to explain the concept, and it is not the result of running a real message queue. The time values (0.05s to save, 0.01s to put in the queue, 3s timeout) are examples. Even with a direct call, you can add a timeout and exception handling to keep the order from failing, and the cases where the queue itself goes down, message loss, duplicate delivery, and ordering problems are not covered here. @RabbitListener in the code is an example for when you use RabbitMQ.

Previous lab: Rate limiting · Next lab: Kafka partitions and consumers

Concepts in this lab

What this lab shows

Settings

Code


      
    

Diagram

Run comparison

Try these