[SpringBoot] Integrate RabbitMQ message individual and batch TTL

Producer side

Directory Structure

import dependencies

Modify yml

Business logic

        Queue message expiration

        Messages expire individually


   

        TTL (Time To Live) survival time. Indicates the survival time when the message is stored in the MQ by the producer, and the message will be automatically cleared when the time arrives. RabbitMQ can set the expiration time for messages individually or for the entire queue (not the queue, but the messages in the queue).

Producer side

Directory Structure

import dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Modify yml

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    #三个类型:none默认不开启确认回调 correlated开启确认回调
    #simple也会确认回调 还会调用waitForConfirms()方法或waitForConfirmsOrDie()方法
    publisher-confirm-type: correlated # 开启确认回调
    publisher-returns: true # 开启退回回调

Business logic

        Queue message expiration

        The first piece of code is to define the names of switches and queues and bind them, which is only the effect of a configuration class. The second piece of code is the method for the producer to generate messages, you only need to care about the logic in the for loop. Figure 1 is the created queue and the 10 messages produced, which will be automatically deleted in 10s. Because the TTL is already defined in the configuration class.

/**
 * 定义交换机与队列的Bean 并且使之绑定
 */
@Component
public class RabbitMQConfig {

    public static final String TTL_EXCHANGE_NAME = "ttl_exchange_name";
    public static final String TTL_QUEUE_NAME = "ttl_queue_name";

    @Bean("ttlExchange")
    public Exchange ttlExchange(){
        return ExchangeBuilder.topicExchange(TTL_EXCHANGE_NAME).durable(true).build();
    }

    //配置队列的时候顺带上ttl()方法 其内部对MQ设置了参数"x-message-ttl"
    //注意这里的单位是毫秒 所以我写的参数为10000毫秒即10秒
    @Bean("ttlQueue")
    public Queue ttlQueue(){
        return QueueBuilder.durable(TTL_QUEUE_NAME).ttl(10000).build();
    }

    @Bean
    public Binding ttl(@Qualifier("ttlExchange") Exchange exchange,
                       @Qualifier("ttlQueue") Queue queue){
        return BindingBuilder.bind(queue).to(exchange).with("test.#").noargs();
    }
}
@SpringBootTest
@RunWith(SpringRunner.class)
class RabbitmqProducerApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void testTTL(){
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                if(b) System.out.println("交换机成功接受到了消息");
                else System.out.println("消息失败原因" + s);
            }
        });
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int i, String s, String s1, String s2) {
                System.out.println("队列接受不到交换机的消息进行了失败回调");
            }
        });
        // 以上代码只是保证消息传递的可靠性 与TTL无关
        for(int i = 0; i < 10; ++i){
            rabbitTemplate.convertAndSend(RabbitMQConfig.TTL_EXCHANGE_NAME,"test.heHe","HelloWorld");
        }
    }
}

                                                                 figure 1

        Messages expire individually

         The configuration class here is still the same as above: the messages in the queue automatically expire in 10s, and then one of the messages can be processed to better understand the difference between the two types of expiration: one of the messages is set to automatically expire in 5s, as can be found in Figure 2 There are 11 messages in the queue, which becomes 10 messages after 5s, and no messages after another 5s.

@SpringBootTest
@RunWith(SpringRunner.class)
class RabbitmqProducerApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void testTTL(){
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                if(b) System.out.println("交换机成功接受到了消息");
                else System.out.println("消息失败原因" + s);
            }
        });
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int i, String s, String s1, String s2) {
                System.out.println("队列接受不到交换机的消息进行了失败回调");
            }
        });
        // 以上代码只是保证消息传递的可靠性 与TTL无关
        // 消息的后处理对象 设置一些消息的参数信息
        MessagePostProcessor messagePostProcessor = new MessagePostProcessor(){
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration("5000");//设置消息对象5s后过期
                return message;
            }
        };
        //消息单独5s过期
        rabbitTemplate.convertAndSend(RabbitMQConfig.TTL_EXCHANGE_NAME,"test.heHe","HelloWorld",messagePostProcessor);
        //队列中的消息全体10s过期
        for(int i = 0; i < 10; ++i){
            rabbitTemplate.convertAndSend(RabbitMQConfig.TTL_EXCHANGE_NAME,"test.heHe","HelloWorld");
        }
    }
}

                                                                 figure 2

        Did you really think it was over at this point? When I put the 10 messages of the for loop on the single expired message, I found a new continent: the initial message was also 11 as shown in Figure 2, but, after that One message will not be eliminated after 5s, but all 11 messages will be deleted after 10s. So I guess that the storage queue of this message is like a stack. Although the survival time of the message produced first is short, it cannot get out when other messages are pressed on its head. Instead, it must wait for itself to be the top element of the stack. You can get out of the stack!

Guess you like

Origin blog.csdn.net/m0_65563175/article/details/130463749