RabbitMQ高级特性第4篇-延迟队列

一、前言

本文演示的延迟队列是基于SpringBoot整合RabbitMQ来实现的,关于SpringBoot整合RabbitMQ可参考该链接:https://blog.csdn.net/pkxwyf/article/details/105158608

二、延迟队列概述和原理

2.1、什么是延迟队列

所谓延迟队列,即消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。

2.1、延迟队列应用场景

  • 用户下单后,30分钟未支付,取消订单恢复库存。

2.3、延迟队列实现原理

很可惜的是在RabbitMQ中并未提供延迟队列功能,但是可以使用:TTL+死信队列 组合实现延迟队列的效果

三、延迟队列代码演示

3.1、消息生产方代码实现

1、编写配置类:定义交换机和队列信息


@Configuration
public class RabbitMQConfig {
    // 普通交换机名称
    public static final String EXCHANGE_NAME = "order_topic_exchange";
    // 普通队列名称
    public static final String QUEUE_NAME = "order_queue";

    // 死信交换机名称
    public static final String DEAD_EXCHANGE_NAME = "dead_order_topic_exchange";
    // 死信队列名称
    public static final String DEAD_QUEUE_NAME = "dead_order_queue";

    // 1. 定义普通交换机
    @Bean("orderExchange")
    public Exchange createExchange(){
        return ExchangeBuilder.topicExchange(EXCHANGE_NAME).durable(true).build();
    }

    // 2. 定义普通队列
    @Bean("orderQueue")
    public Queue createQueue(){
        // 创建map集合:封装队列参数
        Map<String,Object> map = new HashMap<>();
        // 设置死信交换机名称
        map.put("x-dead-letter-exchange", DEAD_EXCHANGE_NAME);
        // 设置发送给死信交换机的routingKey
        map.put("x-dead-letter-routing-key", "dead.order.news");
        // 设置队列过期时间:单位毫秒
        map.put("x-message-ttl", 10000);
        return QueueBuilder.durable(QUEUE_NAME).withArguments(map).build();
    }

    // 3. 定义死信交换机
    @Bean("deadOrderExchange")
    public Exchange createDeadExchange(){
        return ExchangeBuilder.topicExchange(DEAD_EXCHANGE_NAME).durable(true).build();
    }

    // 4. 定义死信队列
    @Bean("deadOrderQueue")
    public Queue createDeadQueue(){
        // 创建map集合:封装队列参数
        return QueueBuilder.durable(DEAD_QUEUE_NAME).build();
    }

    // 5. 队列与交换机绑定关系
    @Bean
    public Binding bindExchangeAndQueue(@Qualifier("orderQueue") Queue queue,
                                        @Qualifier("orderExchange") Exchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with("order.#").noargs();
    }

    // 6. 死信队列与死信交换机绑定关系
    @Bean
    public Binding bindDeadExchangeAndQueue(@Qualifier("deadOrderQueue") Queue queue,
                                        @Qualifier("deadOrderExchange") Exchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with("dead.order.#").noargs();
    }

}

2、编写测试类:发送消息到MQ中

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestDelayQueue {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 测试延迟队列
     */
    @Test
    public void testSendStr() throws Exception{
        // 发送消息
        // 参数1:交换机名字
        // 参数2:路由键
        // 参数3:消息字符串
        rabbitTemplate.convertAndSend(
                "order_topic_exchange",
                "order.news",
                "用户下单成功,订单ID:1");
    }
}

3.2、消息消费方代码实现

@Component
public class RabbitMQConfig {
    /**
     * 监听mq消息
     */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = "dead_order_topic_exchange",type = "topic"),
            value = @Queue(value = "dead_order_queue",durable = "true"),
            key = "dead.order.#"
    ))
    public void handlerMessage(Message message, Channel channel)throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 1. 转换消息
            System.out.println(new String(message.getBody()));
            // 2. 业务处理
            System.out.println("执行业务处理...");
            System.out.println("根据订单id查询状态...");
            System.out.println("判断是否支付成功...");
            System.out.println("取消订单,回滚库存...");
            // 3. 手工签收
            channel.basicAck(deliveryTag,true);
        } catch (Exception e) {
            // 4. 拒绝签收
            channel.basicNack(deliveryTag,true,false);
        }
    }
}

四、延迟队列小结

  1. 延迟队列指消息进入队列后,可以被延迟一定时间再进行消费。
  2. RabbitMQ没有提供延迟队列功能,但可以使用:TTL+DLX实现延迟队列效果。
发布了24 篇原创文章 · 获赞 1 · 访问量 6399

猜你喜欢

转载自blog.csdn.net/pkxwyf/article/details/105168130
今日推荐