- 生产者把消息发布到交换器上;
- 教习最终到达队列,并被消费者接收;
- 绑定决定了消息如何从路由器路由到特定的队列。
RabbitMQ入门 |
RabbitMQ
持久化必要条件(缺一不可)
AMQP
durable
是否持久化
arguments
其他参数
交换器说到底只是一个名称和一个队列绑定列表,正是信道(channel)按照绑定匹配的结果,将消息路由到队列
由于交换器只不过是一张查询表,而不是实际上的消息路由器,因此将交换器在整个集群中进行复制会更加简单
优点:集群中的每个节点拥有每个交换器的所有信息意味着不用担心在节点故障时重新声名交换器,只需要让故障节点上的生产者重新连接到集群上,它们就能立即开始往交换器上发布消息。
内存节点还是磁盘节点
集群中至少需要一个磁盘节点,所有其他节点都可以是内存节点
当节点加入或者离开集群时,必须要将该变更通知到至少一个磁盘节点
如果掉线的是仅有的一个磁盘节点,集群依然可以继续路由消息,但是不能做以下操作
- 创建队列
- 创建交换器
- 创建绑定
- 添加用户
- 更改权限
- 添加或删除集群节点(需要所有磁盘节点都在线才能做的操作)
解决方案
设置至少两个磁盘节点
创建集群
停止当前节点 rabbitmqctl stop_app
重置节点元数据和状态 rabbitmqctl reset
加入到集群节点 rabbitmqctl join_cluster [name]@[hostname]
使用 --ram 参数变成磁盘节点
启动节点 rabbitmqctl start_app
镜像队列
说明
镜像队列的主拷贝仅存在于一个节点(主队列,master)上
其他节点上拥有从队列(slave)拷贝
一旦队列主节点不可用,最老的从队列将被选举为新的主队列
管理
创建
在channel的queueDeclare方法中声名最后一个map类型的参数
{"x-ha-policy":"all"}
all表示让队列镜像到所有集群的节点上,如果声名之后又增加节点,则新增加的节点会自动托管一份队列的从拷贝
将镜像队列镜像到指定节点上
{
"x-ha-policy" : "nodes",
"x-ha-policy-params" : [
"rabbit1@host1",
"rabbit2@host2"
]
}
查看
rabbitmqctl list_queues name pid slave_pids
注意事项
为了使队列镜像到指定节点中,必须在程序中硬编码,如果任何一个节点发生故障或者从集群中移除,那么该声名就会失败,同时也不利于后续扩展,所以尽可能采用all来设置x-ha-policy
虽然是叫从队列(从拷贝),但是从队列的消息是从交换器(信道)直接发送过来的,并不是从主队列复制过来的,所以可以想象成镜像队列拥有一个隐藏的fanout交换器
由于从队列的消息是从交换器直接投递的,所以新增的从队列并不会拥有还未消费的旧消息
使用发送方确认模式时,只有在所有主从拷贝队列安全地接收到消息时才会收到确认通知
故障
主拷贝的节点故障
所有消费者需要重新附加并监听新的队列主拷贝
主拷贝消费者
会自动选取新的队列主拷贝
从拷贝消费者
RabbitMQ会发送给这些消费者一个消费者取消通知(consumer cancellation),此时程序会抛出异常,应用程序就会知道已经不再附加到队列上了,需要重新附加
如果使用的AMQP客户端库不支持消费者取消通知,客户端就无法知道队列的主拷贝已不存在,程序会以为队列里没有消息可用,然而此时消息却被积压在其他从拷贝队列中,因此在不支持消费者取消通知的AMQP客户端应该避免使用镜像队列。
已经消费但尚未确认的消息会重新入队到原来队列的位置
从拷贝的节点故障
所有消费者都不会感知到,不会影响正常工作