• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Y-wee
博客园    首页    新随笔    联系   管理     

rabbimq死信

rabbimq死信

死信的概念

先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,一般来说,producer 将消息投递到 broker 或者直接到queue 里了,consumer 从 queue 取出消息进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列

应用场景

应用场景:为了保证订单业务的消息数据不丢失,需要使用到 RabbitMQ 的死信队列机制,当消息消费发生异常时,将消息投入死信队列中.还有比如说: 用户在商城下单成功并点击去支付后在指定时间未支付时自动失效

死信的来源

  • 消息 TTL 过期
  • 队列达到最大长度(队列满了,无法再添加数据到 mq 中)
  • 消息被拒绝(basic.reject 或 basic.nack)并且 requeue=false

代码实现

普通消费者

package com.yl.dead;

import com.rabbitmq.client.*;
import com.yl.util.RabbitConstant;
import com.yl.util.RabbitUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 普通消费者
 *
 * @author Y-wee
 */
public class ConsumerNormal {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitUtils.getConnection();
        Channel channel = connection.createChannel();

        // 存放普通队列参数,key是固定的,不是自定义的
        Map<String, Object> arguments=new HashMap<>();
        // 消息过期时间,可以不设置,由生产者提供
//        arguments.put("x-dead-letter-exchange",10000);
        // 死信交换机
        arguments.put("x-dead-letter-exchange",RabbitConstant.EXCHANGE_DEAD);
        // 死信队列路由
        arguments.put("x-dead-letter-routing-key","deadKey");
        // 设置普通队列最大长度
//        arguments.put("x-max-length",6);

        // 声明普通队列和普通队列的交换机并进行绑定
        channel.exchangeDeclare(RabbitConstant.EXCHANGE_NORMAL, BuiltinExchangeType.DIRECT);
        channel.queueDeclare(RabbitConstant.QUEUE_NORMAL,false,false,false,arguments);
        channel.queueBind(RabbitConstant.QUEUE_NORMAL,RabbitConstant.EXCHANGE_NORMAL,"normalKey");

        // 声明死信队列和死信队列的交换机并进行绑定
        channel.exchangeDeclare(RabbitConstant.EXCHANGE_DEAD,BuiltinExchangeType.DIRECT);
        channel.queueDeclare(RabbitConstant.QUEUE_DEAD,false,false,false,null);
        channel.queueBind(RabbitConstant.QUEUE_DEAD,RabbitConstant.EXCHANGE_DEAD,"deadKey");

        DeliverCallback deliverCallback = (consumerTag, message) -> {
            String msg = new String(message.getBody());
            if (msg.equals("info7")){
                System.out.println("普通队列拒绝接收此消息:"+msg);
                // 拒绝消费消息,第一个参数是消息标识,第二个参数表示拒绝后是否重新放入队列,false为不放回,反之放回
                channel.basicReject(message.getEnvelope().getDeliveryTag(),false);
            }else {
                System.out.println("普通队列接收到消息:"+msg);
                channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
            }
        };

        CancelCallback cancelCallback = (consumerTag) -> {
        };

        channel.basicConsume(RabbitConstant.QUEUE_NORMAL,false,deliverCallback,cancelCallback);
    }

}

RabbitUtils是笔者自定义的一个工具类,用来获取连接

RabbitConstant是笔者自定义的一个常量类,里面存储了队列名和交换机名

死信消费者

package com.yl.dead;

import com.rabbitmq.client.*;
import com.yl.util.RabbitConstant;
import com.yl.util.RabbitUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 死信消费者
 *
 * @author Y-wee
 */
public class ConsumerDead {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitUtils.getConnection();
        Channel channel = connection.createChannel();

        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("死信队列接收到消息:"+new String(message.getBody()));
            channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
        };

        CancelCallback cancelCallback = (consumerTag) -> {
        };

        channel.basicConsume(RabbitConstant.QUEUE_DEAD,false,deliverCallback,cancelCallback);
    }

}

生产者

package com.yl.dead;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.yl.util.RabbitConstant;
import com.yl.util.RabbitUtils;

import java.io.IOException;

/**
 * 生产者
 *
 * @author Y-wee
 */
public class DeadProvider {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitUtils.getConnection();
        Channel channel = connection.createChannel();

        // 设置死信消息过期时间
//        AMQP.BasicProperties basicProperties=new AMQP.BasicProperties().builder().expiration("10000").build();

        for (int i = 0; i < 10; i++) {
            String message="info"+i;
            channel.basicPublish(RabbitConstant.EXCHANGE_NORMAL,"normalKey",null,message.getBytes());
        }
    }

}
记得快乐
posted @ 2022-02-12 17:53  Y-wee  阅读(66)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3