RabbitTMQ实战 高效部署分布式消息队列笔记

戏子无情 提交于 2020-02-29 21:55:58

一、概念部分

1.各种常见MQ比较

ActiveMQ性能和稳定性较差 适用于中小型企业
kaffka不支持事务,对消息的重复、丢失、错误没有严格要求 性能最高 内存存储
RocketMQ java开发的,商业版支持分布式事务
RabbitMQ Erlang开发的,基于AMQP协议实现,稳定性可靠性很高,性能不错
RabbitMQ提供可靠性投递(confirm)、返回模式(return)

2.AMQP协议

1)AMQP(Advanced Message Queuing Protocal,高级消息队列协议)
2)Server:又称Broker,接受客户端的链接,实现AMQP实体服务
3)Channel:网络信道,几乎所有的操作都在Channel中进行,Channel是进行消息读写的通道。客户端可以建立多Channel,每个Channel代表一个会话任务。 用程序会和代理服务器之间创建一条TCP连接,即AMQP信道。信道是建立在真实TCP连接内的虚拟连接,每条信道会被指派一个唯一ID。建立和销毁TCP会话开销很大,信道方式不会给系统TCP栈造成额外负担。
4)Messaage:消息,由标签Properties和承载数据body组成。
5)Virtual host:虚拟主机,用于进行逻辑隔离,是最上层消息路由。
一个Virtual host里面可以有若干个Exchange和Queue,同一个Virtual host里面Exchange和Queue不能同名。
6)Exchange:交换机,接收消息,根据路由键发送消息到绑定的队列。
7)Binding:绑定,Exchange和Queue之间的虚连接,可以设置 routing key。
8)Routing key:路由规则。
9)Queue:消息队列。

3.基本操作命令

rabbitmq-server 服务器和应用启动
rabbitmqctl stop 服务器和应用关闭
rabbitmqctl stop_app 关闭应用
rabbitmqctl start_app 启动应用
rabbitmqctl status 节点状态
rabbitmqctl add_vhost vhostname 创建虚拟主机
rabbitmqctl delete_vhost vhostname 删除虚拟主机
rabbitmqctl list_vhosts 查看虚拟主机

4.Exchange交换机

1)属性

Type:交换机类型direct、topic、fanout、headers
Durability:是否需要持久化,true为持久化
Auto Delete:当绑定到Exchanges上的队列删除后,自动删除该Exchanges
Internal:当前Exchanges是否用于RabbitMQ内部使用,默认False
Arguments:扩展参数

Direct Exchange
需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。
Fanout Exchange
发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。Fanout交换机转发消息是最快的。
Topic Exchange
对象队列上需要预先绑定Topic。Exchange将路由键和若干Topic进行模糊匹配。符合的topic所关联的队列都会收到消息。
符号“#”匹配一个或多个词,符号“”匹配不多不少一个词。因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.” 只会匹配到“audit.irs”。
Default Exchange
当创建一个队列时,他会自动绑定到默认交换机,并以队列名做为路由键。

5.Queue 消息队列

Durability:是否持久化,Durable:是,Transient:否
Auto delete:最后一个监听移除后,Queue是否自动删除
exclusive:队列是否私有

6.虚拟主机

虚拟主机本质上是一个mini版的RabbitMQ服务器,不同虚拟主机是隔离的

二、操作部分

1.消费订阅方式

1)通过AMQP的basic.consume命令订阅 信道置为自动接收模式 推模式
2)通过AMQP的basic.get命令 主动拉取一条数据 拉模式

2.消息确认方式

1)通过AMQP的basic.ack命令,显式地向RabbitMQ发送确认消息
2)订阅队列时设置auto_ack为true,消费者接到消息就视为确认
3)通过AMQP的basic.reject命令,拒绝接收消息
当reject的参数requeue=true时,消息会发送给其他消费者
当reject的参数requeue=false时,消息会被从队列上删除

如果消费者订阅了队列,消息会立刻发送给订阅的消费者。
如果消息到达了无人订阅的队列,消息会在队列中等待。
如果程序崩溃,未能确认,消息会被发送给其他消费者,在消息确认前不会向故障消费者发送消息。
队列中有多个消费者时,消息会以轮询的方式发送给消费者,每条消息只会发送给一个消费者。

3.队列创建

生产者和消费者都可以创建队列 queue.declare
exclusive=true则队列为私有的
auto-delete=true 最后一个监听移除后,Queue自动删除

4.持久化

1)RabbitMQ重启后,交换机和队列都会清除。需要设置每个交换机和队列的Durable属性为true,则重启后不会清除。
2)RabbitMQ重启后,消息数据都会清除。需要设置投递模式(delivery mode)为2,持久化。
即RabbitMQ的消息持久化,需要将交换机/队列/消息都设置为持久化才可以。
3)持久化机制
持久化将导致RabbitMQ的性能至少下降10倍,在集群中持久化工作的不是很好。
RabbitMQ在收到消息后,会先将消息写入到日志文件,再响应客户端已经收到消息。等收到消费者的确认消费消息后,会在日志文件中将其标记为等待垃圾收集。

5.配置文件

默认位于/etc/rabbitmq/rabbitmq.config
使用Mnesia存储数据

6.双向通信

默认情况下,RabbitMQ时发后即忘的单向流程,通过在AMQP消息头中设置reply_to字段,可以实现双向通信。
通过这种方式可以实现RPC过程调用。

三、集群

主备模式:在并发和数据量不大的情况下,是一种简单易用的HA架构。也称为Warrent模式。
镜像模式:最经典的时Mirror镜像模式,可以保证数据100%不丢失。
多活模式:数据中心异地部署时的主流模式,一般用federation插件同步数据

1.RabbitMQ内建集群

RabbitMQ内建集群不能保证消息的万无一失。即使已经设置了消息持久化、当一个节点崩溃后,节点上的队列消息也会消失。
RabbitMQ默认不会将队列的内容复制到整个集群,队列默认仅存在于队列所属的那个节点上。
RabbitMQ会记录交换器/绑定/队列/虚拟主机/集群的元数据,元数据在所有节点上都会存在一份,但队列消息数据只会有一份。
可以创建内存节点(RAM Node)和磁盘节点(disk Node),但是集群中至少要有一个磁盘节点。
如果磁盘节点全部崩溃了,集群仍可工作,但不能创建交换器/队列/绑定等元数据操作了。

2.镜像队列

镜像节点在集群中的其他节点上拥有从队列,一旦主节点不可用,最老的从节点将成为新的主节点。
声明队列时通过x-ha-policy参数设定镜像节点。
镜像的主从节点切换后,会发送<消费者取消通知>,客户端应该支持该通知,以便重新附加到新的主节点上。

3.保证信息可靠性投递

1)使用AMQP事务
2)发送方确认模式

4.插件的安装与使用

1)启用插件
rabbitmq-plugins enable XXXX
rabbitmqctl stop
rabbitmq-server -detached
2)关闭插件
rabbitmq-plugins disable XXXX
rabbitmqctl stop
rabbitmq-server -detached

5.性能保证

1)qos服务质量保证

在auto_ack为false的前提下 对consume或channel设置qos值进行限流
我们可以通过设置Prefetch count来限制Queue每次发送给每个消费者的消息数,比如我们设置prefetchCount=1, 则Queue每次给每个消费者发送一条消息;消费者处理完这条消息后Queue会再给该消费者发送一条消息。

2)消费端重回队列

TTL(Time To Live,生存时间) 可以在消息或队列上设置过期时间

3)死信队列DLX(DeadLetterExchange)

死信的产生
a.消息被拒绝(base.reject/basic.nack) 且requeue=false
b.TTL过期
c.队列达到最大长度
当消息在一个队列中变成死信,它能被重新publish到另一个Exchange,这个Exchange就是DLX
死信队列也是一个正常的交换机、队列、绑定,原队列通过设置"x-dead-letter-exchange":"死信队列名",将另一个队列指明为自己的死信队列。

4)Return Listener消息机制

Return Listener用于处理一些不可路由的消息!
当我们发送消息时,当前的exchange不存在或者指定的路由key路由不到,这个时候如果我们需要监听这种不可达的消息,就要使用Return Listener.
当Mandatory为true时,监听器会接收到路由不可达的消息,并进行后续处理;当为false时,broker会自动删除该消息。可以在不存在的时候自动创建。

三、业务场景

1.迅速消息发送

不进行落库操作,不做可靠性保障,追求最大吞吐量。

2.确认消息发送

→业务数据与消息数据同时入库(先业务后消息)
→发送消息给MQ
→MQ发送确认送达ack
→更新消息数据库状态
→定时补偿重发超时的任务。

3.批量消息发送

可以进行批量化发送,针对某一原子业务去处理,但不保证可靠性,需要补偿机制。

4.延迟消息发送

加载延迟发送插件,设置delayTime属性。

5.顺序消息

→数据入库 参照确认消息发送
→发送的顺序消息必须发送到同一队列,该队列只能由一个消费者。
→需要统一提交,(可以是一个大消息,也可以拆成多个小消息),所有消息的会话ID保持一致。
→添加消息属性:顺序号,SIZE等。
→消费者获取消息后,先落库。
→消费者向自己发送延迟处理消息,预估消息全部到达后,再进行统一顺序处理。
→定时补偿任务

6.事务消息发送

保证性能的前提下,补偿机制最合适。

7.保证消息幂等

通过统一消息ID,保证幂等性

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!