@[toc] Will messages in RabbitMQ expire if they are not consumed for a long time? Those of you who have used RabbitMQ may have this question, and Songo is here to clarify it.

1. Default

First let’s look at the default.

By default, messages do not expire, that is, if you do not set any parameters when sending a message, the message will not expire, even if the message is not consumed, it will always be stored in the queue.

I don’t need to show you the code in this case, but songo’s previous articles on RabbitMQ are basically like this.

2. TTL

TTL (time-to-live) : indicates the TTL of a message, that is, the validity period of the message. If we want messages to have a lifetime, we can do this by setting the TTL. If a message has lived longer than the TTL and has not been sent yet, the message becomes dead.

The TTL can be set in two different ways:

  1. When declaring a queue, we can set the expiration date of the message in the queue property so that all messages entering the queue have the same expiration date.
  2. The message validity period is set when the message is sent, so that different messages have different validity periods.

What if you set both of them?

Whichever is shorter shall prevail.

When we set the message validity period, the message will be deleted from the queue when it expires. However, there are some differences in the corresponding deletion timing between the two methods:

  1. In the first case, when the message queue is set to expire, the message will be deleted, because the message enters a message queue, and the head of the queue is the earliest message to expire, so RabbitMQ only needs a scheduled task to scan the header for expired messages. If so, just delete it.
  2. For the second option, when the information will not be deleted immediately after expiration, but when the message to deliver to consumers to delete, because the second way, every message expiration time is different, want to know which message expired, must want to iterate through all the messages in the queue can be realized, when the message is long so it is more cost performance, So in the second case, the message is deleted only when it is delivered to the consumer.

With TTL out of the way, let’s look at its use.

For the rest of the code, Songo uses AMPQ packaged in Spring Boot as an example.

2.1 A Single Message Expires

Let’s start with the expiration time of a single message.

Start by creating a Spring Boot project to introduce Web and RabbitMQ dependencies as follows:

Then configure RabbitMQ connection information in application.properties as follows:

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
Copy the code

Next, configure the message queue a little:

@Configuration
public class QueueConfig {

    public static final String JAVABOY_QUEUE_DEMO = "javaboy_queue_demo";
    public static final String JAVABOY_EXCHANGE_DEMO = "javaboy_exchange_demo";
    public static final String HELLO_ROUTING_KEY = "hello_routing_key";

    @Bean
    Queue queue(a) {
        return new Queue(JAVABOY_QUEUE_DEMO, true.false.false);
    }

    @Bean
    DirectExchange directExchange(a) {
        return new DirectExchange(JAVABOY_EXCHANGE_DEMO, true.false);
    }

    @Bean
    Binding binding(a) {
        returnBindingBuilder.bind(queue()) .to(directExchange()) .with(HELLO_ROUTING_KEY); }}Copy the code

This configuration class does three main things: configure message queues, configure switches, and bind the two together.

  1. New Queue: The first parameter is the name of the message Queue. The second parameter indicates whether the message is persistent; The third parameter indicates whether the message queue is exclusive, which is usually set to false. The fourth parameter indicates that if the queue does not have any consumers subscribing, the queue will be automatically deleted, generally for temporary queues.
  2. Configure a DirectExchange switch.
  3. Bind the switch and queue together.

This configuration should be simple, there is no explanation, there is an exclusivity, Songo here a little more:

In terms of exclusivity, if set to true, the message queue is accessible only to the Connection that created it. No other Connection can access the message queue. If you try to redeclare or access the exclusive queue on a different Connection, the system will report a resource locked error. For exclusive queues, on the other hand, when the connection is broken, the message queue is automatically deleted (regardless of whether the queue is declared persistent or not).

A message sending interface is provided as follows:

@RestController
public class HelloController {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @GetMapping("/hello")
    public void hello(a) {
        Message message = MessageBuilder.withBody("hello javaboy".getBytes())
                .setExpiration("10000") .build(); rabbitTemplate.convertAndSend(QueueConfig.JAVABOY_QUEUE_DEMO, message); }}Copy the code

When creating the Message object, we can set the expiration time of the Message, which is set to 10 seconds.

That’s it!

Next, let’s start the project and test the message sending. When a message is successfully sent, it is not consumed because there are no consumers. Open the RabbitMQ administration page, click on the Queues TAB and after 10s the message has disappeared:

It’s simple!

To set the expiration time for a single message, you need to set the expiration time for the message when it is sent.

2.2 Queue Message Expired

Set the message expiration time for the queue as follows:

@Bean
Queue queue(a) {
    Map<String, Object> args = new HashMap<>();
    args.put("x-message-ttl".10000);
    return new Queue(JAVABOY_QUEUE_DEMO, true.false.false, args);
}
Copy the code

After setting up, we modify the sending logic of the message as follows:

@RestController
public class HelloController {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @GetMapping("/hello")
    public void hello(a) {
        Message message = MessageBuilder.withBody("hello javaboy".getBytes()) .build(); rabbitTemplate.convertAndSend(QueueConfig.JAVABOY_QUEUE_DEMO, message); }}Copy the code

As you can see, the message can be sent normally, no need to set the message expiration time.

OK, start the project and send a message to test. View the RabbitMQ management page as follows:

As you can see, the Features attributes of the message queue are D and TTL. D indicates that the message in the message queue is persistent, and TTL indicates that the message will expire.

When the page is refreshed 10 seconds later, the number of messages restores to 0.

This is to set the message expiration time for the message queue, once set, all messages entering the queue will have an expiration time.

2.3 Special Circumstances

There is also the special case of setting the TTL to 0, which means that messages will be discarded immediately if they are not consumed immediately. This can be used as a partial replacement for the immediate parameter supported by RabbitMQ3.0. This is because the basic.return method returns the message body if the immediate parameter fails to be delivered (this can be done using a dead-letter queue).

Songo won’t show you the code, but this should be easier.

3. Dead-letter queues

Some friends can’t help but ask, where is the deleted message? Was it really deleted? No, no, no! So that brings us to dead-letter queues, so let’s look at dead-letter queues.

3.1 Dead-letter Switch

A dead-letter Exchange is a dead-letter Exchange.

A Dead letter switch is used to receive Dead messages. What are Dead messages? A general message can become a dead-letter message in the following ways:

  • The message was rejected (basic.reject/basic.nack) and the Requeue parameter was set to false
  • Message expiration
  • The queue length reaches the maximum. Procedure

When a message becomes a dead letter message in a queue, it is sent to the DLX. The message queue bound to the DLX is called a dead letter queue.

The DLX is essentially a normal switch, you can assign a DLX to any queue, and when there is a dead letter in the queue RabbitMQ will automatically publish the dead letter to the DLX and route it to another dlX-bound queue (the dead letter queue).

3.2 Dead letter queue

This is easy to understand. A queue bound to a dead letter switch is a dead letter queue.

3.3 practice

Let’s look at a simple example.

First we create a dead letter switch, then create a dead letter queue, and bind the dead letter switch and the dead letter queue together:

public static final String DLX_EXCHANGE_NAME = "dlx_exchange_name";
public static final String DLX_QUEUE_NAME = "dlx_queue_name";
public static final String DLX_ROUTING_KEY = "dlx_routing_key";

/** * Configure a dead-letter switch **@return* /
@Bean
DirectExchange dlxDirectExchange(a) {
    return new DirectExchange(DLX_EXCHANGE_NAME, true.false);
}
/** * Configure a dead letter queue *@return* /
@Bean
Queue dlxQueue(a) {
    return new Queue(DLX_QUEUE_NAME);
}
/** * Bind a dead letter queue to a dead letter switch *@return* /
@Bean
Binding dlxBinding(a) {
    return BindingBuilder.bind(dlxQueue())
            .to(dlxDirectExchange())
            .with(DLX_ROUTING_KEY);
}
Copy the code

This is no different than a normal switch, a normal message queue.

Next configure a dead-letter switch for the message queue as follows:

@Bean
Queue queue(a) {
    Map<String, Object> args = new HashMap<>();
    // Set the message expiration time
    args.put("x-message-ttl".0);
    // Set a dead-letter switch
    args.put("x-dead-letter-exchange", DLX_EXCHANGE_NAME);
    // Set a dead letter routing_key
    args.put("x-dead-letter-routing-key", DLX_ROUTING_KEY);
    return new Queue(JAVABOY_QUEUE_DEMO, true.false.false, args);
}
Copy the code

Just two parameters:

  • X-dead-letter-exchange: configures a dead-letter exchange.
  • X-dead-letter-routing-key: configures dead letterrouting_key.

That’s all configured.

Future messages sent to this message queue, if nack, reject, or expired, will be sent to the DLX and then to the dlX-bound message queue.

Dead-letter message queues consume the same as regular message queues:

@RabbitListener(queues = QueueConfig.DLX_QUEUE_NAME)
public void dlxHandle(String msg) {
    System.out.println("dlx msg = " + msg);
}
Copy the code

It’s easy

4. Summary

RabbitMQ message expiration: RabbitMQ message expiration: RabbitMQ message expiration

Public number Jiangnan little Rain background reply to the title of this article, you can get the case download link.

References:

  • blog.csdn.net/u012988901/article/details/88958654