RabbitMQ的高级特性(四)-----死信队列


  1. 死信队列DLX:DeadLetter Exchange(死信交换机),当消息成为Dead message后,可以被重新发送到另一个交换机,这个交换机就是DLX。
  2. 消息成为死信的三种情况:
    • 队列消息数量到达限制;比如给队列最大只能存储10条消息,当第11条消息进来的时候存不下了,第11条消息就被称为死信
    • 消费者拒接消费消息,basicNack/basicReject,并且不把消息重新放入原目标队列,requeue=false;
    • 原队列存在消息过期设置,消息到达超时时间未被消费;
  3. 死信的处理方式:
    • 丢弃,如果不是很重要,可以选择丢弃
    • 记录死信入库,然后做后续的业务分析或处理
    • 通过死信队列,由负责监听死信的应用程序进行处理
  4. 队列绑定死信交换机:
    • 给队列设置参数: x-dead-letter-exchange 和 x-dead-letter-routing-key
  5. 过期时间代码demo:
    1. spring-rabbitmq-producer.xml
      
      
      
      
      	
      	
      		
      		
      		
      		
      		
      		
      		
      		
      	
      
      
      
      	
      		
      	
      
      
      
      
      	
      		
      	
      
      
    2. 发送消息
      /**
       * 发送测试死信消息:
       *  1. 过期时间
       *  2. 长度限制
       *  3. 消息拒收
       */
      @Test
      public void testDlx(){
      	//1. 测试过期时间,死信消息
      	rabbitTemplate.convertAndSend("test_exchange_dlx","test.dlx.haha","我是一条消息,我会死吗?");
      }
      
  6. 长度限制代码实现
    • 发送消息
      /**
       * 发送测试死信消息:
       *  1. 过期时间
       *  2. 长度限制
       *  3. 消息拒收
       */
      @Test
      public void testDlx(){
      	//1. 测试过期时间,死信消息
      	//rabbitTemplate.convertAndSend("test_exchange_dlx","test.dlx.haha","我是一条消息,我会死吗?");
      
      	//2. 测试长度限制后,消息死信
      	for (int i = 0; i < 20; i++) {
      		rabbitTemplate.convertAndSend("test_exchange_dlx","test.dlx.haha","我是一条消息,我会死吗?");
      	}
      }
      
  7. 测试消息拒收
    1. spring-rabbitmq-consumer.xml
      
      	
      	
      	
      	
      
      
    2. 消费端拒收:
      @Component
      public class DlxListener 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. 处理业务逻辑
      			System.out.println("处理业务逻辑...");
      			int i = 3/0;//出现错误
      			//3. 手动签收
      			channel.basicAck(deliveryTag,true);
      		} catch (Exception e) {
      			//e.printStackTrace();
      			System.out.println("出现异常,拒绝接受");
      			//4.拒绝签收,不重回队列 requeue=false
      			channel.basicNack(deliveryTag,true,false);
      		}
      	}
      }
      
    3. 发送消息:
      /**
       * 发送测试死信消息
       *  1. 过期时间
       *  2. 长度限制
       *  3. 消息拒收
       */
      @Test
      public void testDlx(){
      	//1. 测试过期时间,死信消息
      	//rabbitTemplate.convertAndSend("test_exchange_dlx","test.dlx.haha","我是一条消息,我会死吗?");
      
      	//2. 测试长度限制后,消息死信
      	//        for (int i = 0; i < 20; i++) {
      	//            rabbitTemplate.convertAndSend("test_exchange_dlx","test.dlx.haha","我是一条消息,我会死吗?");
      	//        }
      	//3. 测试消息拒收
      	rabbitTemplate.convertAndSend("test_exchange_dlx", "test.dlx.haha", "我是一条消息,我会死吗?");
      }
      
  8. 死信队列小结:
    • 死信交换机和死信队列和普通的没有区别
    • 当消息成为死信后,如果该队列绑定了死信交换机,则消息会被死信交换机重新路由到死信队列
    • 消息成为死信的三种情况:
      1. 队列消息长度(数量)到达限制;
      2. 消费者拒接消费消息,并且不重回队列;
      3. 原队列存在消息过期设置,消息到达超时时间未被消费;

相关