之前我们给我们的系统加了一个使用SpringAOP+RabbitMQ+WebSocket进行实时消息通知功能(https://www.cnblogs.com/little-sheep/p/9934887.html)。在测试环境下没有问题,但上到生产环境后部分用户反映出现了丢消息的情况,针对这个问题我们进行了排查,发现,原本我们的系统是单机的,但用户在之前做了调整,在内外网服务器分别部署了系统,两个服务器都公用一个RabbitMQ。那么问题就来了。

之前生产者向Exchange生产消息,消费者从queue消费消息使用的是direct模式,通过routing-key保证生产的消息只有指定的消费者可消费。但当两台服务器共用一个MQ时即有了两个消费者连接同一个queue,此时rabbitmq并不是一个消息两个消费者都能消费,而是采用默认的轮询发送方式,A服务器收到消息1、3、5 。。。而B服务器收到2、4、6 。。。

这就出现了用户感觉的丢消息现象。所以我们考虑将通知改为广播形式即fanout。

RabbitMQ将消息中间件的实现分成了Exchange+Queue的形式,Exchange和Queue使用Binding;生产者向Exchange生产消息,消息根据指定的binding进入Queue,消费者从Queue取消息。Fanout模式如图:

一个消费者会对应一个queue,那么多个消费者要有多个queue。

修改后代码如下:

RabbitMQConfig.java

//声明exchange
Connection connection = factory.createConnection();
Channel channel = connection.createChannel(false);
//生产环境中有多个server,每个server都是一个消费者,对同一个消息都要进行处理。选用广播模式
channel.exchangeDeclare("exchange.websocket.msg", BuiltinExchangeType.FANOUT);

RabbitMessageQueue.java

@Override
public void send(WebSocketMsgEntity entity) {
logger.warn("::product msg to MQ-websocket_msg_queue!");
//若没有指定exchange,则使用默认名为“”的exchange,binding名与queue名相同
rabbitTemplate.convertAndSend("exchange.websocket.msg","", entity);
}

RabbitMQListener.java

@Component
public class RabbitMQListener {
private static Logger logger = LoggerFactory.getLogger(RabbitMQListener.class);
@Autowired
private RabbitMQService mqService;
/**
* WebSocket推送监听器
* @param socketEntity
* @param deliveryTag
* @param channel
*/
@RabbitListener(bindings ={@QueueBinding(value = @Queue(exclusive = "true"), exchange = @Exchange(value = "exchange.websocket.msg", type = ExchangeTypes.FANOUT))})
public void webSocketMsgListener(@Payload WebSocketMsgEntity socketMsgEntity, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, Channel channel) throws IOException {
logger.warn("::consume msg from MQ-websocket_msg_queue!");
mqService.handleWebSocketMsg(socketMsgEntity, deliveryTag, channel);
} }

原本的客户端监听是监听Queue,而现在改成监听Binding。并不显式的指定一个Queue,而是将Queue设置成exclusive = true,这样每个消费者在监听Binding时都会默认创建一个Queue与指定的Exchange绑定,在消费者断开连接后Queue自动删除。若有两个消费者,则创建两个Queue,他们绑定的Exchange相同,当生产者有消息时会向两个Queue各插入一条,那么两个系统的用户就都能收到通知啦!

RabbitMQ踩坑记的更多相关文章

  1. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  2. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

  3. 【踩坑记】从HybridApp到ReactNative

    前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...

  4. Spark踩坑记——共享变量

    [TOC] 前言 Spark踩坑记--初试 Spark踩坑记--数据库(Hbase+Mysql) Spark踩坑记--Spark Streaming+kafka应用及调优 在前面总结的几篇spark踩 ...

  5. Spark踩坑记——从RDD看集群调度

    [TOC] 前言 在Spark的使用中,性能的调优配置过程中,查阅了很多资料,之前自己总结过两篇小博文Spark踩坑记--初试和Spark踩坑记--数据库(Hbase+Mysql),第一篇概况的归纳了 ...

  6. djangorestframework+vue-cli+axios,为axios添加token作为headers踩坑记

    情况是这样的,项目用的restful规范,后端用的django+djangorestframework,前端用的vue-cli框架+webpack,前端与后端交互用的axios,然后再用户登录之后,a ...

  7. HttpWebRequest 改为 HttpClient 踩坑记-请求头设置

    HttpWebRequest 改为 HttpClient 踩坑记-请求头设置 Intro 这两天改了一个项目,原来的项目是.net framework 项目,里面处理 HTTP 请求使用的是 WebR ...

  8. vue踩坑记

    vue踩坑记 易错点 语法好难啊qwq 不要把'data'写成'date' 在v-html/v-bind中使用vue变量时不需要加变量名 在非vue事件中使用vue中变量时需要加变量名 正确 < ...

  9. 【bug记录】OS Lab4 踩坑记

    OS Lab4 踩坑记 Lab4在之前Lab3的基础上,增加了系统调用,难度增加了很多.而且加上注释不详细,开玩笑的指导书,自己做起来困难较大.也遇到了大大小小的bug,调试了一整天. 本文记录笔者在 ...

随机推荐

  1. 转载 CoreCLR源码探索(七) JIT的工作原理(入门篇)

    转载自:https://www.cnblogs.com/zkweb/p/7687737.html 很多C#的初学者都会有这么一个疑问, .Net程序代码是如何被机器加载执行的? 最简单的解答是, C# ...

  2. iOS动态库和静态库的运用

    概念认识 什么是库 库是共享程序代码的方式,库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.在开发过程中,一些核心技术或者常用框架,出于安全性和稳定性的考虑,不想被外界知道,所以会把 ...

  3. Oracle导出/导入数据方法--两种方法(pde格式/dmp格式)

    转至:https://www.cnblogs.com/houbxblogs/articles/13365557.html?ivk_sa=1024320u 1.导出数据方法一(pde格式) 工具→ 导出 ...

  4. 哈工大 信息安全实验 XSS跨站脚本攻击原理与实践

    XX大学XX学院 <网络攻击与防御> 实验报告 实验报告撰写要求 实验操作是教学过程中理论联系实际的重要环节,而实验报告的撰写又是知识系统化的吸收和升华过程,因此,实验报告应该体现完整性. ...

  5. qt(一)

    一.Qt安装 qt离线安装地址:http://download.qt.io/archive/qt/ 参考教程:https://blog.csdn.net/u013934107/article/deta ...

  6. cpolar——安全的内网穿透工具

    什么是cpolar? cpolar是一种安全的内网穿透云服务,它将内网下的本地服务器通过安全隧道暴露至公网,使得公网用户可以正常访问内网服务. 它能用在哪些场景? 微信公众号开发,实时断点调试微信消息 ...

  7. LeetCode-025-K 个一组翻转链表

    K 个一组翻转链表 题目描述:给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保 ...

  8. 微信小程序 实现图片上传并展示到前端(多文件)并实现表单提交验证

    链接: https://blog.csdn.net/guanj0623/article/details/121595884?spm=1001.2014.3001.5501 https://blog.c ...

  9. centos网卡配置修改

    centos网卡配置文件一般位于:/etc/sysconfig/network-scripts/ 文件名一般为:ifcfg-eno或者ifcfg-eth0类似的文件,可以先用ip addr 命令或者是 ...

  10. 3、myql的逻辑架构和sql的执行流程

    msyql逻辑架构 逻辑架构的解析 逻辑架构图如下(序号代表的是:服务器处理客户端请求的流程) 1.1connectors connectors是指使用不同语言的客户端与mysql server服务器 ...