RabbitMQ的高级特性【二】

5.死信队列

Dead Letter Exchange(死信交换机),当消息成为Dead message后,可以被重新发送到另一个交换机,这个交换机就是DLX。

消息成为死信的三种情况:

1、队列的消息达到了限制时;

2、消费者拒绝接收消费消息,basicNack/basicReject,且不把消息重新放入目标队列中,requeue为false;

3、原队列存在消息过期设置,消息到达超时时间未被消费;

队列绑定死信交换机:

设置参数: x-dead-letter-exchange 和 x-dead-letter-routing-key

配置:

 /**
     *  声明正常的队列,设置x-dead-letter-exchange和x-dead-letter-routing-key
     *  过期时间 100000
     */
    @Bean("itemTopicQueue")
    public Queue topicQueue(){
        return QueueBuilder.durable(queue_name).withArgument("x-message-ttl",100000)
                //x-dead-letter-exchange:死信交换机名称
                .withArgument("x-dead-letter-exchange","exchange_dlx")
                // x-dead-letter-routing-key:发送给死信交换机的routingkey
                .withArgument("x-dead-letter-routing-key","dlx.e").build();
    }

    /**
     * 声明死信队列
     * @return
     */
    @Bean("dlxQueue")
    public Queue dlxQueue(){
        return QueueBuilder.durable("queue_dlx").build();
    }

    /**
     * 声明死信交换机
     * @return
     */
    @Bean("dlxTopicQueue")
    public Exchange dlxExchange(){
        return ExchangeBuilder.topicExchange("exchange_dlx").durable(true).build();
    }
    /**
     * 绑定交换机
     */
    @Bean
    public Binding dlxQueueExchange(@Qualifier("dlxTopicQueue") Exchange exchange,
                                     @Qualifier("dlxQueue") Queue queue){
        //routingkey为绑定规则
        //   #通配多级
        return BindingBuilder.bind(queue).to(exchange).with("dlx.#").noargs();
    }
@Component
public class AckListener implements ChannelAwareMessageListener {
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            //1.接收消息
            System.out.println(new String(message.getBody()));
            //2.业务处理逻辑
            //TODO
            //假如出现异常
            int i=4/0;
            //3.手动签收
            channel.basicAck(deliveryTag,true);
        } catch (Exception e) {
            //4.拒绝签收 requeue=false 不重回队列,成为死信
            channel.basicNack(deliveryTag,true,false);
            //channel.basicReject(deliveryTag,true)
        }
    }
    @Override
    public void onMessage(Message message) {
        ChannelAwareMessageListener.super.onMessage(message);
    }
}

6.延迟队列

消息进入队列后不会立即消费,只有在指定时间后才会被消费。

比如提交订单后10分钟未支付自动取消订单,回滚库存

实现方法:定时器,延迟队列

rabbitmq中未提供延迟队列的功能。但是可以使用TTL+死信队列组合实现延迟队列的效果

步骤:

  1. 定义正常交换机(order_exchange)和队列(order_queue)

  2. 定义死信交换机(order_exchange_dlx)和队列(order_queue_dlx)

  3. 绑定,设置正常队列过期时间为30分钟

配置:

 /**
     *  声明交换机
     * @return
     */
    @Bean("orderTopicExchange")
    public Exchange topicExchange(){
        return ExchangeBuilder.topicExchange("order_exchange").durable(true).build();
    }

    /**
     *  声明正常的队列,设置x-dead-letter-exchange和x-dead-letter-routing-key
     *  过期时间 10000 --10秒钟
     */
    @Bean("oderTopicQueue")
    public Queue topicQueue(){
        return QueueBuilder.durable("order_queue").withArgument("x-message-ttl",10000)
                //x-dead-letter-exchange:死信交换机名称
                .withArgument("x-dead-letter-exchange","order_exchange_dlx")
                // x-dead-letter-routing-key:发送给死信交换机的routingkey
                .withArgument("x-dead-letter-routing-key","dlx.order.quxiao").build();
    }

    /**
     * 声明死信队列
     * @return
     */
    @Bean("dlxQueue")
    public Queue dlxQueue(){
        return QueueBuilder.durable("queue_dlx").build();
    }

    /**
     * 声明死信交换机
     * @return
     */
    @Bean("dlxTopicQueue")
    public Exchange dlxExchange(){
        return ExchangeBuilder.topicExchange("order_exchange_dlx").durable(true).build();
    }
    /**
     * 绑定交换机
     */
    @Bean
    public Binding dlxQueueExchange(@Qualifier("dlxTopicQueue") Exchange exchange,
                                     @Qualifier("dlxQueue") Queue queue){
        //routingkey为绑定规则
        //   #通配多级
        return BindingBuilder.bind(queue).to(exchange).with("dlx.oder.#").noargs();
    }

    /**
     * 绑定交换机
     */
    @Bean
    public Binding itemQueueExchange(@Qualifier("orderTopicExchange") Exchange exchange,
                                     @Qualifier("oderTopicQueue") Queue queue){
        //routingkey为绑定规则
        //   #通配多级
        return BindingBuilder.bind(queue).to(exchange).with("order.#").noargs();
    }

发送端

 /**
     * 测试延迟队列-订单过期
     */
    @Test
    public void testOder() throws InterruptedException {
        //发送消息
        rabbitTemplate.convertAndSend("order_exchange","order.demo","消息...");
        //10秒倒计时
        for(int i=10;i>0;i--){
            System.out.println(i+"秒后过期...");
            Thread.sleep(1000);
        }
        System.out.println("已过期...");
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值