- AMQP协议
1.协议模型
1.协议连接步骤
1.1.生产者与服务建立连接----》连接host ----》exchange
1.2.Connection :建立连接
1.3.Channel:网络信道,是进行消息的读写的通道,客户端可建立多个channel,每个channel代表一个任务。
1.4.Message:由properties 和body组成。Properties可以对消息进行设置:是否延迟,发送时 机
1.5.Virtual host: 虚拟地址。进行逻辑隔离,是最上层的消息路由,比如说mq服务可能要关联多个业务服务,每个业务服务会需要对应一个独立的区域。一个virtual host 可以有多个exchange和queue。但同一个virtual host里面的exchange和queue的名称不能相同。
1.6.Exchange:路由。生产者把消息发送到路由器上
1.7.Bingding:exchange和Queue之间的虚拟连接,bingding可以包含routing key。
-
- Routing key:路由规则,虚拟机用其确认如何路由一个指定的消息,
- Queue:消息队列。
2. 交换机exchange
2.1 架构图
2.2.基本属性
2.2.1.type: direct , topic , fanout , headers ,( sharding 需要安装插件 )
2.2.2.Durability:是否需要持久化,true为需要
2.2.3.Auto Delete :
当最后一个绑定到Ecchange上的队列删除后,自动删除该exchange,即没有队列关联路由了
2.2.4.Internal:
当前exchange 是否用于MQ内部使用,默认为false。
Argurments
2.3 Direct 路由
即:所有发送到Direct Echange的消息被转发到RouteKey中指定的Queue
Direct模式可以使用RabbiMq自带的Exchange:default Exchange ,所以不需要将Exchange 进行任何绑定操作,消息传递时RouteKey 必须完全匹配才会被队列接收,否则消息被抛弃。
2.4. Topic
即:所有发送到Topic exchange的消息被转发到所有关系RouteKey中指定Topic的Queue上
Exchange将RouteKey和某个Topic进行模糊匹配
此时队列需要绑定一个topic
三.消息投递及确认
3.1 消息投递的保证
3.1.1. 生产端的可靠性投递
解析:生产端要把要发送的消息持久化而不是直接发送。
B.confirm Listener :接收消费端的消息是否被消费成功。True就是成功了
如果step3 由于网络抖动,消费端没有把成功消费的消息告知生产者。
则
C.Retry send :生产端可以设置一个消息超时时间,如果超时后会重新发送
即保证消息成功发出,且发送端收到MQ接口broker确认应答
还有消息的补偿机制
C.收到消息的持久化
D.消息的延迟投递,做二次确认,回调检查
3.1.2 可靠性投递三
在高并发场景下的消息投递
即消息的延迟投递,做二次确认,回调检查
主要是减少数据库操作,
解析:stop1:生产消息
Step2 :若干时间后订阅消息被消费的确认通知,该通知由回调服务发送
Step4:如果消息被正常消息则向mq发送消息服务通知回调服务
Step5:监听消息被正常消费后持久化数据
Step6:如果消息消费失败,则发起补偿通知给消息的生产者
- Upstream service: 生产端,上游服务
第一步把发送的消息先入库
DownStream service :消费端
C.CallBack service :回调服务
D.MQ Broker:
备注:在整个业务链条中没有任何分布式事务
3.1.3 . 消息的幂等性
3.1.3.1. 消费端保证消息的幂等性
即数据库的乐观锁
A.在海量订单的业务高峰期,如何避免消息重复消费?
即:消费端实现消息的幂等性
- 主流方案:(1)唯一ID+指纹码机制,利用数据库主键去重
Select count( 1 ) from table where id = 唯一ID+指纹码机制(业务规则)
好处:实现简单
缺点:高并发下对数据库的写入的性能瓶颈
解决方案:ID进行分库分表进行算法路由。
(2)利用redis原子性去重
3.2 消息的ACK和重回队列
可靠性投递
3.2.1 确认机制实现
A.第一步,在channel上开启确认模式:channel。confirmSelect();
B. 第二步,在channel上添加监听,addConfirmListener,监听成功和识别的返回结果,根据具体的结果对消息进行重新发送或记录日志后续处理
3.2.2 return 消息机制
A.return Listener 用于处理一些不可路由消息:即发送的消息当前的exchange不存在或者路由的key路由不到。这个时候就要监听这种不可达的消息,使用Return Listener
3.2.3.生产者发送消息后怎么样确认mq服务器是否收到消息
两各方式:
- AmQP 实现了事务机制
事务机制
- Txselect
用户将当期channel设置成transation模式,trCommit用于提交事务,如果有异常则txRollback回滚
- 消息可靠性投递confirm 模式
生产者端confirm模式的实现原理:
3.3 消息限流
3.3.1 消费端的限流
Eg:RabbitMq 服务器有数万条消息,当
RabbitMq提供了一种qos(服务质量保证)功能,
3.3 消费端ACK与重回队列
3.3.1 手工ACK和NACK
A.消费端未消费成功,程序本身的异常,业务异常,可以进行消息补偿
B.演技
3.3.2. 消费端的重回队列
A.对于没有成功消费的消息重新给broker
3.3.3. API 使用说明
3.4 TTL消息
解释:RabbitMq 支持消息的过期时间,当消息发送时可以指定消息生存时间
RabbitMq也支持队列的过期时间,从消息的入队列开始计算,只要超过了队列的超时时间,则消息会自动清除。
3.4.1
3.5 死信队列—DLX
3.5.1 当消息在队列中变成死信,
3.5.2 消息变成死信的途径
A.消息被拒绝 且request=false
B.消息TTL过期
C.队列长度最大
四.RabbitMq 使用
- 使用方式种类:
- 单发送多接受
- 发布订阅模式
2. 怎样保证消息的稳定性
2.1. publisher confirms :发布方确认
2.2. message 持久化
2.3 acknowlegement :Consumer 确认
3.怎样避免消息丢失
3.1 将Queue 和message 都设置为可持久化,还有就是使用事务,
- RabbitMq 持久化的特点
- 如果要在重启后保持消息的持久化必须设置消息是持久化的标识
4.消息的广播类型
4.1.fanout广播模式
4.2.direct 广播模式
4.3 topic 广播模式
5. 怎样实现延迟消息队列??
5.1 延迟任务通过消息的TTL 和 Dead letter exchange来实现。
我们需要建立2个队列,一个用于发送消息,一个用于消息过期后的转发目标队列
6.RabbitMq 集群作用
6.1 集群里面可以共享user,vhost ,queue,exchange ,
所有的数据和状态都是必须在所有节点上覆制的。一个例外是
7.rabbitMq的节点类型
7.1 内存节点
7.2 磁盘节点
五.RabbitMq 集群架构
1. 主备架构模式
主节点可以提供读写,但从节点不做任何事情,只在主节点宕机时,从节点替代主节点服务。这个主从的模式是有本质区别的。这个架构在并发量低的业务可以使用
这个模式activemq 利用zk 做主备一样。
1.1 主备架构设计
- Haproxy:是一个tcp基别的代理,
其配置如下:
Bind 0.0.0.0:5672 #配置tcp模式
Mode tcp #简单的轮询
Balance roundrobin #主节点
Server bhz76 IP :5672 check inter 5000 rise 2 fall 2
Server bhz77 IP:5672 backup check inter 5000 rise 2 fall 2 #备用节点
说明:集群节点配置#inter每个5秒对mq集群做健康检查,2次正确证明服务器可用,3次失败证明服务器不可用
2.远程模式架构
2.1 说明:远程模式可以实现双活的一种模式,简称shovel模式,
即把消息进行不同数据中心的复制,可以跨地域让多个mq集群互联
3.镜像模式架构Mirror
3.1 Mirror镜像队列,
为了保证rabbitm数据的高可用解决方案,主要是实现数据的同步,一般是
3个节点,该模式可保证数据完全不丢失。
3.2.架构图
-
-
- keepAlived:
-
4.多活模式
4.1 是实现异地数据复制的主流模式,
因为shovel模式配置复杂。这个模式依赖插件:federation插件,可实现AMQP的数据通信
4.2. 架构图
Federation exchange:不需要构建cluster,在brokers之间传输消息。连接的双方可使用不同的users和virtual hosts 。双方也可以
六.镜像集群搭建
1.服务组件
2.keepAlived
主要是通过VRRP(虚拟路由器冗余协议)协议实现高可用功能,
- 三个作用:
- 管理LVS软件
- 实现LVS集群的监控检测
- 集群配置
- hipe_compile: erlang compiler编译小提示性能
- vm_memory_high_watermark:内存低水位线,若地域该水位线,则
七.RabbitMq 设计架构整体方案
1.实现思路
2.架构完成功能:
- 支持消息高序列化的转化和异步发送
- 支持消费和生产的实例的连接池化缓存化,
- 支持可靠性投递,保障消息不能丢失
- 支持消费端的幂等性操作,避免消费端重复消费
- 支持快速消息发送,在日志收集,统计分析等需求下保证高吞吐量
- 支持延迟消息模式,消息可以延迟发送,指定延迟时间,用于延迟检查,服务限流场景
- 支持事务消息,保障100%可靠性投递,
- 支持顺序消息,保障消息送达消费端的前后顺序,例如下订单等复合操作
- 支持消息补偿,重试,快速定位异常,失败消息
- 支持消息集群负载均衡,保障消息落到具体set集群
- 支持消息路由策略
3.生产端组件说明
3.1.RabbitTemplateContainer : RabbitTemplate复用池,高并发下可以重复利用
-
- RabbitTemplateConfirmCallback
4. 消费端组件
4.1.AsycnMessageInter:
4.2. IdempotenRabbitHandler:消费者幂等性保障拦截器
5.架构模式说明
5.1迅速发送消息模式
6. 事务消息
Eg:单笔大额现金交易,希望这个消息优先级最高,且可靠性要求100%。和银行系统都要兼顾,所以要有补偿机制,主动发起银行查询指令机制。
6.1. txSelect 和confirmSelect 机制
支持事务,传统的RabbitMq自身的事务和spring机制在高并发下会消耗系统资源出现阻塞
。因此采用可靠性投递机制,就是补偿机制。数据源使用一个,也就是业务操作的DB2和消息记录操作DB1使用的是一个数据库源。可以用一个数据库实例,但是两个数据库
最后利用spring DataSourceTransactionManager 在本地进行发送消息,当消息发送失败时可进行补偿。
6.2.消息的幂等性
6.2.1. 非幂等性:
A.可靠性消息投递机制
B. MQ broker 服务于消费端传输消息的过程中的网络抖动
3.3.2.幂等性设计架构
说明:
- 需要有全局唯一id
- ID路由组件:将信息入库,因为单点压力过大
当然也可以通过redis做持久化