赞
踩
我们项目中很多地方都使用了RabbitMQ,RabbitMQ是我们项目中服务通信的主要方式之一,我们项目中服务通信主要有两种方式实现:
1.通过Feign实现服务调用
2.通过MQ实现服务通信
基本上除了查询请求之外,大部分的服务调用都采用的是MQ实现的异步调用,例如:
1.发布内容的异步审核
2.验证码的异步发送
3.用户行为数据的异步采集入库
4.搜索历史记录的异步保存
5.用户信息修改的异步通信(用户修改信息之后,同步修改其他服务中的冗余/缓存的用户信息)
6.静态化页面的生成
7.MYSQL和Redis,ES之间的数据同步
选择使用RabbitMQ是因为RabbitMQ的功能丰富,支持各种消息收发模式(简单队列模式,工作队列模式,路由模式,直接模式,主题模式),支持延迟队列,惰性队列而却天然支持集群,保证服务的高可用,同时性能非常不错,社区也比较活跃,文档资料非常丰富
使用MQ有很多好处:
吞吐量提升:无需等待订阅者处理完成,响应更快速
故障隔离:服务没有直接调用,不存在级联失败问题
调用之间没有阻塞,不会造成无效的资源占用
耦合度极低,每个服务都可以灵活插拔,可替换
流量削峰:不管发布事件的流量波动多大,都有Broker接收,订阅者可以按照自己的速度去处理事件
使用MQ也有很多的缺点:
1.架构太复杂了,业务没有明显的流程线,不好管理
2.需要依赖于Broker的可靠,安全,性能
消息发送到交换机失败会向生产者返回ACK,生产者通过回调接收发送结果,如果发送失败,重新发送,或者记录日志人工介入
消息从交换机路由到队列失败会向生产者返回失败原因,生产者通过回调接收回调结果,如果发送失败,重新发送,或者记录日志人工介入
设计一个消息状态表,主要包含:消息id,消息内容,交换机,消息路由key,发送时间,签收状态等字段,发送方业务执行完毕后,向消息状态表保存一条消息记录,消息状态为未签收,之后在向MQ发送消息,消费方接收消息消费完毕之后,向发送方发送一条签收消息,发送方接收到签收消息之后,修改消息状态表中的消息状态为已签收!之后通过定时任务扫描消息状态表中这些未签收的消息,重新发送消息,直到成功为止,对于已经完成消费的消息定时清理即可!
解决方案:
1.每条消息设置一个唯一的标识id
2.幂等方案
1).token+Redis
2).分布式锁
3).数据库锁(悲观锁,乐观锁)
1. 提高消费者的消费能力
(使用多线程消费)
2.增加更多的消费者,提高消费速度
(使用工作队列模式,设置多个消费者消费,消费同一个队列中的信息)
3.扩大队列容积,提高堆积上限
使用RabbitMQ惰性队列
1).接收到消息后直接存入磁盘而非内存
2).消费者要消费消息时才会从磁盘中读取并加载到内存
3).支持数百万的消息存储
一个队列只设置一个消费者消费即可 , 多个消费者之间是无法保证消息消费顺序
性的
RabbitMQ的延迟队列有二种实现方案 :
1. 使用消息过期TTL + 死信交换机
2. 使用延迟交换机插件
1.为队列设置过期时间,所有进到这个对消的消息都会具有统一的过期时间
2.为消息单独设置过期时间
注意:
1.队列过期和消息过期同时存在,会以时间短的时间为准
2.RabbitMQ队列消息过期的机制是判断队列头部元素是否过期,如果队里头部消息没有到过期时间,中间消息到了过期时间,这个消息也不会被自动剔除
当一个队列中的消息满足下列情况之一时,就会成为死信(dead letter):
1.消费者使用basic.reject或 basic.nack声明消费失败,并且消息的requeue参数
设置为false
2.消息是一个过期消息,超时无人消费
3.要投递的队列消息满了,无法投递
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。