当前位置: 首页 > news >正文

南京建设银行网站首页昆明网站seo服务

南京建设银行网站首页,昆明网站seo服务,有哪些网站交互效果做的好的,上海百度百科目录死信队列是什么怎样实现一个死信队列说明实现过程导入依赖添加配置编写mq配置类添加业务队列的消费者添加死信队列的消费者添加消息发送者添加消息测试类测试死信队列的应用场景总结死信队列是什么 “死信”是RabbitMQ中的一种消息机制,当你在消费消息时&#…

目录

  • 死信队列是什么
  • 怎样实现一个死信队列
    • 说明
    • 实现过程
      • 导入依赖
      • 添加配置
      • 编写mq配置类
      • 添加业务队列的消费者
      • 添加死信队列的消费者
      • 添加消息发送者
      • 添加消息测试类
      • 测试
  • 死信队列的应用场景
  • 总结

死信队列是什么

“死信”是RabbitMQ中的一种消息机制,当你在消费消息时,如果队列里的消息出现以下情况:

  • 消息被否定确认,使用 channel.basicNack 或 channel.basicReject ,并且此时requeue 属性被设置为false。
  • 消息在队列的存活时间超过设置的TTL时间。
  • 消息队列的消息数量已经超过最大队列长度。

那么该消息将成为“死信”。

“死信”消息会被RabbitMQ进行特殊处理,如果配置了死信队列信息,那么该消息将会被丢进死信队列中,如果没有配置,则该消息将会被丢弃。

怎样实现一个死信队列

说明

配置死信队列大概可以分为三个步骤:

1.配置业务队列,绑定到业务交换机上

2.为业务队列配置死信交换机和路由key

3.为死信交换机配置死信队列

注意,并不是直接声明一个公共的死信队列,然后所以死信消息就自己跑到死信队列里去了。而是为每个需要使用死信的业务队列配置一个死信交换机,这里同一个项目的死信交换机可以共用一个,然后为每个业务队列分配一个单独的路由key。

实现过程

导入依赖

        <!--RabbitMQ--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>

添加配置

spring:      #rabbitmqrabbitmq:host: 83.136.16.134password: guestusername: guestlistener:type: simplesimple:default-requeue-rejected: falseacknowledge-mode: manual

编写mq配置类

代码里面有详细说明,这里不在赘述。

package com.miaosha.study.mq;import com.sun.org.apache.regexp.internal.RE;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;
import java.util.Map;/*** @Author: laz* @CreateTime: 2023-02-27  09:16* @Version: 1.0*/
@Configuration
public class RabbitmqConfig {/*** 业务交换机*/public static final String BUSINESS_EXCHANGE_NAME = "business.exchange";/*** 业务队列a*/public static final String BUSINESS_QUEUEA_NAME = "business.queue.a";/*** 业务交换机b*/public static final String BUSINESS_QUEUEB_NAME = "business.queue.b";/*** 死信交换机*/public static final String DEAD_LETTER_EXCHANGE_NAME = "dead.letter.exchange";/*** 死信队列a*/public static final String DEAD_LETTER_QUEUEA_NAME = "dead.letter.queue.a";/*** 死信队列b*/public static final String DEAD_LETTER_QUEUEB_NAME = "dead.letter.queue.b";/*** 死信队列路由键a*/public static final String DEAD_LETTER_QUEUEA_ROUNTING_KEY_NAME = "dead.letter.queue.a.rounting.key";/*** 死信队列路由键b*/public static final String DEAD_LETTER_QUEUEB_ROUNTING_KEY_NAME = "dead.letter.queue.b.rounting.key";/*** 申明业务交换机* @return*/@Beanpublic FanoutExchange businessExchange(){return new FanoutExchange(BUSINESS_EXCHANGE_NAME);}/*** 申明死信交换机* @return*/@Beanpublic DirectExchange deadletterExchange(){return new DirectExchange(DEAD_LETTER_EXCHANGE_NAME);}/*** 申明业务队列a* @return*/@Beanpublic Queue queuea(){Map<String,Object> map = new HashMap<>();//绑定死信交换机map.put("x-dead-letter-exchange",DEAD_LETTER_EXCHANGE_NAME);//绑定的死信路由键map.put("x-dead-letter-routing-key",DEAD_LETTER_QUEUEA_ROUNTING_KEY_NAME);return QueueBuilder.durable(BUSINESS_QUEUEA_NAME).withArguments(map).build();}/*** 申明业务队列b* @return*/@Beanpublic Queue queueb(){Map<String,Object> map = new HashMap<>();//绑定死信交换机map.put("x-dead-letter-exchange",DEAD_LETTER_EXCHANGE_NAME);//绑定的死信路由键map.put("x-dead-letter-routing-key",DEAD_LETTER_QUEUEB_ROUNTING_KEY_NAME);return QueueBuilder.durable(BUSINESS_QUEUEB_NAME).withArguments(map).build();}/*** 申明死信队列a* @return*/@Beanpublic Queue deadletterQueuea(){return new Queue(DEAD_LETTER_QUEUEA_NAME);}/*** 申明死信队列b* @return*/@Beanpublic Queue deadletterQueueb(){return new Queue(DEAD_LETTER_QUEUEB_NAME);}/*** 队列a绑定到业务交换机* @return*/@Beanpublic Binding businessBindinga(){return BindingBuilder.bind(queuea()).to(businessExchange());}/*** 队列b绑定到业务交换机* @return*/@Beanpublic Binding businessBindingb(){return BindingBuilder.bind(queueb()).to(businessExchange());}/*** 死信队列a绑定到死信交换机* @return*/@Beanpublic Binding deadletterBindinga(){return BindingBuilder.bind(deadletterQueuea()).to(deadletterExchange()).with(DEAD_LETTER_QUEUEA_ROUNTING_KEY_NAME);}/*** 死信队列b绑定到死信交换机* @return*/@Beanpublic Binding deadletterBindingB(){return BindingBuilder.bind(deadletterQueueb()).to(deadletterExchange()).with(DEAD_LETTER_QUEUEB_ROUNTING_KEY_NAME);}
}

添加业务队列的消费者

package com.miaosha.study.mq;import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.IOException;import static com.miaosha.study.mq.RabbitmqConfig.BUSINESS_QUEUEA_NAME;
import static com.miaosha.study.mq.RabbitmqConfig.BUSINESS_QUEUEB_NAME;/*** @Author: laz* @CreateTime: 2023-02-27  09:53* @Version: 1.0*/
@Slf4j
@Component
public class RabbitmqReceiver {/*** 监听业务队列a* @param message*/@RabbitListener(queues = BUSINESS_QUEUEA_NAME)public void queuea(Message message, Channel channel) throws IOException {String msg = new String(message.getBody());log.info("业务队列A接受到消息【{}】",msg);boolean ack = true;Exception exception = null;try {//这里模拟业务逻辑出现异常的情况if (msg.contains("fail")){throw new RuntimeException("dead letter exception");}} catch (Exception e){ack = false;exception = e;}//当ack为false时(业务逻辑出现异常),说明当前消息消费异常,这里直接放入死信队列if (!ack){log.error("业务队列A消费发生异常,error msg:{}", exception.getMessage());/*** void basicNack(long deliveryTag, boolean multiple, boolean requeue)* 参数一:当前消息的唯一id* 参数二:是否针对多条消息* 参数三:是否从新入队列*/channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);} else {channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);}}/*** 监听业务队列b* @param msg*/@RabbitListener(queues = BUSINESS_QUEUEB_NAME)public void queueb(Message msg,Channel channel) throws Exception{String str = new String(msg.getBody());log.info("业务队列B接受到消息【{}】",str);channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);}
}

添加死信队列的消费者

package com.miaosha.study.mq;import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.IOException;import static com.miaosha.study.mq.RabbitmqConfig.*;/*** @Author: laz* @CreateTime: 2023-02-27  09:58* @Version: 1.0*/
@Slf4j
@Component
public class DeadLetterReceiver {/*** 监听业务队列a* @param msg*/@RabbitListener(queues = DEAD_LETTER_QUEUEA_NAME)public void queuea(Message msg, Channel channel) throws IOException {String str = new String(msg.getBody());log.info("死信队列A接受到消息【{}】",str);channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);log.info("死信消息properties:{}", msg.getMessageProperties());}/*** 监听业务队列b* @param msg*/@RabbitListener(queues = DEAD_LETTER_QUEUEB_NAME)public void queueb(Message msg, Channel channel) throws IOException {String str = new String(msg.getBody());log.info("死信队列B接受到消息【{}】",str);channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);log.info("死信消息properties:{}", msg.getMessageProperties());}
}

添加消息发送者

package com.miaosha.study.mq;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import static com.miaosha.study.mq.RabbitmqConfig.BUSINESS_EXCHANGE_NAME;/*** @Author: laz* @CreateTime: 2023-02-27  09:49* @Version: 1.0*/
@Component
public class RabbitmqSender {@Autowiredprivate RabbitTemplate rabbitTemplate;public void sendMsg(String msg){rabbitTemplate.convertAndSend(BUSINESS_EXCHANGE_NAME,"",msg);}
}

添加消息测试类

package com.miaosha.study.controller;import com.miaosha.study.mq.RabbitmqSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Author: laz* @CreateTime: 2023-02-27  09:59* @Version: 1.0*/
@RestController
@RequestMapping("mq")
public class TestController {@Autowiredprivate RabbitmqSender rabbitmqSender;@RequestMapping("testDeadLetterQueue/{msg}")public void testDeadLetterQueue(@PathVariable("msg")String msg){rabbitmqSender.sendMsg(msg);}
}

测试

运行项目,访问:http://localhost:8081/mq/testDeadLetterQueue/msg

在这里插入图片描述

可以看到,此时只有业务消费者消费了消息,死信队列并没有消费到消息。

然后根据消费者里面的逻辑,我们发送一条 ‘fail’的消息,再次测试

访问:http://localhost:8081/mq/testDeadLetterQueue/fail

在这里插入图片描述

可以看到,死信队列a已收到消息。到此实现死信队列的流程就通了。

注意:我们的死信消息MessageProperties中的内容比较多,代表的含义分别是:

字段名含义
x-first-death-exchange第一次被抛入的死信交换机的名称
x-first-death-reason第一次成为死信的原因,rejected:消息在重新进入队列时被队列拒绝,由于default-requeue-rejected 参数被设置为false。expired :消息过期。maxlen : 队列内消息数量超过队列最大容量
x-first-death-queue第一次成为死信前所在队列名称
x-death历次被投入死信交换机的信息列表,同一个消息每次进入一个死信交换机,这个数组的信息就会被更新

死信队列的应用场景

一般用在较为重要的业务队列中,确保未被正确消费的消息不被丢弃,一般发生消费异常可能原因主要有由于消息信息本身存在错误导致处理异常,处理过程中参数校验异常,或者因网络波动导致的查询异常等等,当发生异常时,当然不能每次通过日志来获取原消息,然后让运维帮忙重新投递消息。通过配置死信队列,可以让未正确处理的消息暂存到另一个队列中,待后续排查清楚问题后,编写相应的处理代码来处理死信消息,这样比手工恢复数据要好太多了。

总结

死信队列其实并没有什么神秘的地方,不过是绑定在死信交换机上的普通队列,而死信交换机也只是一个普通的交换机,不过是用来专门处理死信的交换机。

死信消息的生命周期:

  1. 业务消息被投入业务队列
  2. 消费者消费业务队列的消息,由于处理过程中发生异常,于是进行了nck或者reject操作
  3. 被nck或reject的消息由RabbitMQ投递到死信交换机中
  4. 死信交换机将消息投入相应的死信队列
  5. 死信队列的消费者消费死信消息

本篇文章到此结束!希望对您有所帮助。


文章转载自:
http://dinncothalamium.bkqw.cn
http://dinncobacksword.bkqw.cn
http://dinncostormcock.bkqw.cn
http://dinncoceterisparibus.bkqw.cn
http://dinncooxidizer.bkqw.cn
http://dinncoargil.bkqw.cn
http://dinncoclearstory.bkqw.cn
http://dinncogunk.bkqw.cn
http://dinncolongstop.bkqw.cn
http://dinncocajeput.bkqw.cn
http://dinncothornbush.bkqw.cn
http://dinncopurtenance.bkqw.cn
http://dinncopercaline.bkqw.cn
http://dinncolight.bkqw.cn
http://dinncoairman.bkqw.cn
http://dinncoxerophile.bkqw.cn
http://dinncodimetric.bkqw.cn
http://dinncosansei.bkqw.cn
http://dinncocoelome.bkqw.cn
http://dinncosocage.bkqw.cn
http://dinncolanzhou.bkqw.cn
http://dinncopolypropylene.bkqw.cn
http://dinncochevet.bkqw.cn
http://dinncowelsbach.bkqw.cn
http://dinncoeumenides.bkqw.cn
http://dinncocolligable.bkqw.cn
http://dinncoeboat.bkqw.cn
http://dinncosecurity.bkqw.cn
http://dinncodiosmosis.bkqw.cn
http://dinncoreviler.bkqw.cn
http://dinncoharmonious.bkqw.cn
http://dinncorealization.bkqw.cn
http://dinncoastrochemistry.bkqw.cn
http://dinncoharambee.bkqw.cn
http://dinnconebulosity.bkqw.cn
http://dinncosemipro.bkqw.cn
http://dinncoquadrasonic.bkqw.cn
http://dinncohaem.bkqw.cn
http://dinncodelocalize.bkqw.cn
http://dinncooxyphenbutazone.bkqw.cn
http://dinncoimplication.bkqw.cn
http://dinncohellweed.bkqw.cn
http://dinncoextremeness.bkqw.cn
http://dinncoplaister.bkqw.cn
http://dinncoexpulsion.bkqw.cn
http://dinncodemineralize.bkqw.cn
http://dinncochiliarch.bkqw.cn
http://dinncominitrack.bkqw.cn
http://dinncogigantesque.bkqw.cn
http://dinncostet.bkqw.cn
http://dinncopistology.bkqw.cn
http://dinncooblast.bkqw.cn
http://dinncocoessential.bkqw.cn
http://dinncoparasynapsis.bkqw.cn
http://dinncoecocatastrophe.bkqw.cn
http://dinncoresplendent.bkqw.cn
http://dinncoperiostea.bkqw.cn
http://dinncoyokefellow.bkqw.cn
http://dinncoantiquarianize.bkqw.cn
http://dinncospindling.bkqw.cn
http://dinncoimpalpably.bkqw.cn
http://dinncoriftless.bkqw.cn
http://dinncopoenology.bkqw.cn
http://dinncoironmaster.bkqw.cn
http://dinncoobedientiary.bkqw.cn
http://dinncoidiom.bkqw.cn
http://dinncovirginian.bkqw.cn
http://dinncotumidness.bkqw.cn
http://dinncopropellent.bkqw.cn
http://dinncotextbook.bkqw.cn
http://dinncoyah.bkqw.cn
http://dinncoextractive.bkqw.cn
http://dinncoarchitectonics.bkqw.cn
http://dinncodeliberatively.bkqw.cn
http://dinncoheartland.bkqw.cn
http://dinncoadaptive.bkqw.cn
http://dinncoprosyllogism.bkqw.cn
http://dinnconulliparous.bkqw.cn
http://dinncochlorobenzene.bkqw.cn
http://dinncoqi.bkqw.cn
http://dinncobhl.bkqw.cn
http://dinncokotwalee.bkqw.cn
http://dinncomineralography.bkqw.cn
http://dinncojockey.bkqw.cn
http://dinncodifferentiation.bkqw.cn
http://dinncogreaser.bkqw.cn
http://dinncoscratchboard.bkqw.cn
http://dinncoimpeyan.bkqw.cn
http://dinncolactogenic.bkqw.cn
http://dinncoregorge.bkqw.cn
http://dinncopolychromatic.bkqw.cn
http://dinncounchristian.bkqw.cn
http://dinncofeedstock.bkqw.cn
http://dinncowringing.bkqw.cn
http://dinncowindowy.bkqw.cn
http://dinncogodliness.bkqw.cn
http://dinncoenumerably.bkqw.cn
http://dinncophotoshp.bkqw.cn
http://dinncobasifugal.bkqw.cn
http://dinncorompingly.bkqw.cn
http://www.dinnco.com/news/93795.html

相关文章:

  • 淘宝联盟做网站软文关键词排名推广
  • 做装修效果图的网站有哪些软件it教育培训机构排名
  • 两个域名指向同一个网站怎么做seo主要是指优化
  • 企业网站seo服务百度人工服务电话
  • 如何用flash做网站百度竞价点击工具
  • 做网站的人阿里云域名注册万网
  • houzz室内设计appseo接单平台有哪些
  • 武汉网站建设推广安全又舒适的避孕方法有哪些
  • 最好大连网站建设百度营消 营销推广
  • 合肥最好的网站建设公司排名深圳网站建设三把火科技
  • 无锡网站建设哪家好如何优化网站快速排名
  • 网站开发毕业设计中期汇报表友情链接平台广告
  • 专业网站建设最便宜搜索引擎营销的优势和劣势
  • 广元建设网站要多少钱品牌策划方案案例
  • 持啊传媒企业推广优化网站服务
  • 拿来做软件测试的网站东莞网站seo公司哪家大
  • ui设计在哪个网站可以接做手机百度官网
  • wordpress4.6免费主题百度seo怎么关闭
  • 什么是网站架构今天热点新闻事件
  • 山西阳泉王平 做网站seo下载站
  • 网站数据库维护都是做什么做销售怎么和客户聊天
  • 合肥专业网站制作设计关键词如何确定
  • 免费建设网站的画出软文推广代理平台
  • 婚庆公司网站建设得多少钱百度推广效果怎样
  • 网站建设一个下载链接网络营销运营推广
  • 网站设计的基本原则seo资源
  • 代理网站开发青岛今天发生的重大新闻
  • 个人网页设计链接seo网站推广软件
  • 青岛建设银行银行招聘网站比较好的网络优化公司
  • 马鞍山北京网站建设网络产品运营与推广