[MQ] 死信队列介绍与场景描述
创始人
2024-04-10 14:01:01

✨✨个人主页:沫洺的主页

📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏 

                           📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专栏

                           📖Docker专栏📖Reids专栏📖MQ专栏📖SpringCloud专栏     

💖💖如果文章对你有所帮助请留下三连✨✨

🐣什么是死信

在 RabbitMQ 中充当主角的就是消息,在不同场景下,消息会有不同地表现。

死信就是消息在特定场景下的一种表现形式,这些场景包括:

  1. 消息被拒绝访问,即 RabbitMQ返回 basicNack 的信号时。 或者拒绝basicReject
  2. 消费者发生异常,超过重试次数 。
  3. 消息的 TTL 时间过期。
  4. 消息队列达到最大长度。

上述场景经常产生死信,即消息在这些场景中时,被称为死信。

🐤什么是死信队列 

死信队列就是用于储存死信的消息队列,在死信队列中,有且只有死信构成,不会存在其余类型的消息。

死信队列在 RabbitMQ 中并不会单独存在,往往死信队列都会绑定这一个普通的消息队列,当所绑定的消息队列中,有消息变成死信了,那么这个消息就会重新被交换机路由到指定的死信队列中去,我们可以通过对这个死信队列进行监听,从而手动的去对这一消息进行补偿。

🐓使用死信队列

死信队列基本使用,只需要在声明业务队列的时候,绑定指定的死信交换机和RoutingKey即可。

    //定义业务队列@Beanpublic Queue directQueue() {return QueueBuilder.durable(QNAME).deadLetterExchange(DENAME) //通过这两个配置,使我们的业务队列与死信交换机有关系了.deadLetterRoutingKey(DKEY).ttl(60*1000) //设置消息多久过期,消息超过这个时间就直接给死信交换机,让它处理.maxLength(1000) //设置队列最大容量,超过这个容量就直接给死信交换机,让它处理.build();}

环境搭建

消费者

@Component
public class DeadConsumer {//死信private static final String DENAME = "211-DeadExchage-死信";private static final String DQNAME = "211-DeadQueue-死信";private static final String DKEY = "211-DeadQueue-RoutingKey";//业务private static final String ENAME = "211-DirectExchage-业务";private static final String QNAME = "211-DirectQueue-业务";private static final String KEY = "211-DirectQueue-RoutingKey";//region  队列和交换机的注册//定义死信交换机,本质就是普通的直连交换机@Beanpublic DirectExchange deadExchange() {return new DirectExchange(DENAME, true, false);}//定义死信队列@Beanpublic Queue deadQueue() {return QueueBuilder.durable(DQNAME).build();}//创建死信队列和死信交换机的绑定关系@Beanpublic Binding binding1() {return BindingBuilder.bind(deadQueue()).to(deadExchange()).with(DKEY);}//定义业务交换机@Beanpublic DirectExchange directExchange() {return new DirectExchange(ENAME, true, false);}//定义业务队列@Beanpublic Queue directQueue() {return QueueBuilder.durable(QNAME).deadLetterExchange(DENAME) //通过这两个配置,使我们的业务队列与死信交换机有关系了.deadLetterRoutingKey(DKEY).ttl(60*1000) //设置消息多久过期,消息超过这个时间就直接给死信交换机,让它处理.maxLength(5) //设置队列最大容量,超过这个容量就直接给死信交换机,让它处理.build();}//创建业务队列和业务交换机的绑定关系@Beanpublic Binding binding2() {return BindingBuilder.bind(directQueue()).to(directExchange()).with(KEY);}//endregion//业务消费者@RabbitHandler@RabbitListener(queues = QNAME)public void process1(UserRegisterOk userRegisterOk) {System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss")+"消费者接收消息:" + userRegisterOk.getName()+ "," + userRegisterOk.getAge());}
}

生产者

@Component
public class DeadProducer {@Autowiredprivate RabbitTemplate rabbitTemplate;public void sendMessage(){UserRegisterOk userRegisterOk1 = UserRegisterOk.builder().name("张三").age(18).build();//要将对象序列化,转成字符串,使用消息转换器MessageConverterrabbitTemplate.convertAndSend("211-DirectExchage-业务","211-DirectQueue-RoutingKey",userRegisterOk1);System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss") +"生产者生产消息-->张三发送成功");}
}

启动类

@SpringBootApplication
public class App4 {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App4.class, args);DeadProducer producer = context.getBean(DeadProducer.class);producer.sendMessage();}
}

场景描述: 当没有消费者时,消息的 TTL 时间过期

ttl(60*1000) //设置消息多久过期,消息超过这个时间就直接给死信交换机,让它处理

死信队列一般是没有消费者的,都是通过人工干预去处理

​场景描述: 没有消费者时,消息队列达到最大长度

 生产者发送8条消息,消息队列最大长度为5,多出的3条会放到死信队列里

 maxLength(5) //设置队列最大容量,超过这个容量就直接给死信交换机,让它处理

场景描述: 手动应答下,消息被拒绝访问

#开启消费者应答模式为 auto自动应答 manual手动应答
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#开启消费者自动重试机制,也就是消费者函数只要抛出异常,就会触发重试
spring.rabbitmq.listener.simple.retry.enabled=false

还是生产者发送8条消息,区别是对象年龄不同

@Component
public class DeadProducer {@Autowiredprivate RabbitTemplate rabbitTemplate;public void sendMessage(){for (int i=1;i<=8;i++){UserRegisterOk userRegisterOk1 = UserRegisterOk.builder().name("张三").age(18+i).build();//要将对象序列化,转成字符串,使用消息转换器MessageConverterrabbitTemplate.convertAndSend("211-DirectExchage-业务","211-DirectQueue-RoutingKey",userRegisterOk1);System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss") +"生产者生产消息-->张三发送成功");}}
}

消费者判断对象的年龄,符合就应答,不符合就拒绝应答

    //业务消费者@RabbitHandler@RabbitListener(queues = QNAME)public void process1(UserRegisterOk userRegisterOk,Message message, Channel channel) throws IOException {long deliveryTag = message.getMessageProperties().getDeliveryTag();if(userRegisterOk.getAge()>23){System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss")+"消费者接收消息:" + userRegisterOk.getName()+ "," + userRegisterOk.getAge()+"年龄符合");channel.basicAck(deliveryTag,false);}else {System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss")+"消费者接收消息:" + userRegisterOk.getName()+ "," + userRegisterOk.getAge()+"年龄不符合");channel.basicNack(deliveryTag,false,false);}}

场景描述: 消费者发生异常,超过重试次数

重试5次

#开启消费者应答模式为 auto自动应答 manual手动应答
spring.rabbitmq.listener.simple.acknowledge-mode=auto
#开启消费者自动重试机制,也就是消费者函数只要抛出异常,就会触发重试
spring.rabbitmq.listener.simple.retry.enabled=true
#设置重试最大次数
spring.rabbitmq.listener.simple.retry.max-attempts=5
#设置重试时间最大间隔
spring.rabbitmq.listener.simple.retry.max-interval=8000ms
#设置重试时间间隔
spring.rabbitmq.listener.simple.retry.initial-interval=1000ms
#设置重试时间间隔的倍数
spring.rabbitmq.listener.simple.retry.multiplier=2

模拟消费者异常

    //业务消费者@RabbitHandler@RabbitListener(queues = QNAME)public void process1(UserRegisterOk userRegisterOk) {System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss") +"消费者接收消息:" + userRegisterOk.getName()+ "," + userRegisterOk.getAge());int i=1/0;}

5次之后就不再消费了,将消息放到死信队列里

#超过重试次数后,进入死信队列,默认为false
#重试次数超过上面的设置之后是否丢弃(false不丢弃时需要写相应代码将该消息加入死信队列)
spring.rabbitmq.listener.simple.default-requeue-rejected = false

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...