[000-01-022].第10节:RabbitMQ中的死信队列

我的后端学习大纲

RabbitMQ学习大纲


1、什么是死信:

  • 1.死信,就是无法被消费的消息,字面意思可以这样理解
  • 2.producer 将消息投递到 broker 或者直接到 queue 里了,consumer 从 queue 取出消息进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列

2、死信应用场景:

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

3、产生死信的情况

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

4、死信处理实战:

4.1.死信的架构图:

  • 1个生产者,两个消费者
  • 2个交换机分别是: normal_exchange和dead_exchange,交换机的类型是直接类型
  • 3.队列分别是: normal_queue和dead_queue
  • 4.routing key分别是:zhangsan和lisi
    在这里插入图片描述

4.2.三种死信情况的处理

a.编码实现TTL过期情况:

  • 1.生产者代码:
    在这里插入图片描述
  • 2.消费者 C1 代码(启动之后关闭该消费者 模拟其接收不到消息)
    public class Consumer01 {
     //普通交换机名称
     private static final String NORMAL_EXCHANGE = "normal_exchange";
     //死信交换机名称
     private static final String DEAD_EXCHANGE = "dead_exchange";
     
     public static void main(String[] argv) throws Exception {
    	 Channel channel = RabbitUtils.getChannel();//获取信道
    
    
    	//声明死信交换机和普通交换机类型为 direct
    	 channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
    	 channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);
    	 
    	 //声明死信队列
    	 String deadQueue = "dead-queue";
    	 channel.queueDeclare(deadQueue, false, false, false, null);
    	 
    	 //死信队列绑定死信交换机与 routingkey
    	 channel.queueBind(deadQueue, DEAD_EXCHANGE, "lisi");
    	 
    
    	 //正常队列绑定死信队列信息
    	 Map<String, Object> params = new HashMap<>();	 
    	 //正常队列设置死信交换机 参数 key 是固定值
    	 params.put("x-dead-letter-exchange", DEAD_EXCHANGE);
    	 //正常队列设置死信 routing-key 参数 key 是固定值
    	 params.put("x-dead-letter-routing-key", "lisi");
    	 
    	
    	 // 声明正常队列的名称
    	 String normalQueue = "normal-queue";
    	 channel.queueDeclare(normalQueue, false, false, false, params);
    	 channel.queueBind(normalQueue, NORMAL_EXCHANGE, "zhangsan");
    	 
    
    	 // 正常接收消息的返回值函数
    	 System.out.println("正常接收消息的返回值函数");
    	 DeliverCallback deliverCallback = (consumerTag, delivery) -> {
    	 	String message = new String(delivery.getBody(), "UTF-8");
    	 	System.out.println( "Consumer01 接收到消息"+message);
    	 };
    
    	// 消费端消费队列中的消息,并返回
    	 channel.basicConsume(normalQueue, true, deliverCallback, consumerTag -> {});
    } 
    }
    

在这里插入图片描述

  • 3.消费者 C2 代码(以上步骤完成后 启动 C2 消费者 它消费死信队列里面的消息)
 private static final String DEAD_EXCHANGE = "dead_exchange";
	 public static void main(String[] argv) throws Exception {
	 	Channel channel = RabbitUtils.getChannel();
	 	channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);
	 	String deadQueue = "dead-queue";
	 	channel.queueDeclare(deadQueue, false, false, false, null);
	 	channel.queueBind(deadQueue, DEAD_EXCHANGE, "lisi");
	 	System.out.println("等待接收死信队列消息.....");
		DeliverCallback deliverCallback = (consumerTag, delivery) -> {
		 	String message = new String(delivery.getBody(), "UTF-8");
		 	System.out.println("Consumer02 接收死信队列的消息" + message);
	 };
	 	channel.basicConsume(deadQueue, true, deliverCallback, consumerTag -> {

		});
	 } 
 }

在这里插入图片描述


b.队列达到最大长度:

  • 1.生产者:
    在这里插入图片描述
  • 2.C1 消费者修改以下代码(启动之后关闭该消费者 模拟接收不到消息),注意此时需要把原先队列删除 因为参数改变了
    在这里插入图片描述
  • 3.消费者C2代码不变:
    在这里插入图片描述

c.消息被拒绝:

  • 1.消息生产者代码:
    在这里插入图片描述
  • 2.C1 消费者代码:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 3.消费者C2 代码不变。启动消费者 1 然后再启动消费者 2
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值