项目搭建集群时可能有这样的需求:
- 负载均衡
- 任何节点故障 、或者重启将不会影响我们正常使用某个队列
本文旨在解决两个问题。
1. 项目基本搭建
参考链接
2. 几个要点
2.1 什么是集群
Clustering connects multiple machines together to form a single logical broker.
Communication is via Erlang message-passing, so all nodes in the cluster must have the same Erlang cookie.
The network links between machines in a cluster **must** be reliable, and all machines in the cluster must run the same versions of RabbitMQ and Erlang.
Virtual hosts, exchanges, users, and permissions are automatically mirrored across all nodes in a cluster.
Queues may be located on a single node, or mirrored across multiple nodes.
A client connecting to any node in a cluster can see all queues in the cluster, even if they are not located on that node.
Typically you would use clustering for high availability and increased throughput, with machines in a single location.
以上是官方文档给出的解释。
稍稍说几个地方:
1.安装Erlang环境后有一个.erlang.cookie文件,集群中各节点的正常通信就是以cookie的一致性为基础的,所以必须保证集群中所有节点有相同的cookie;一般情况下文件会在/var/lib/rabbitmq/路径下(如果没有请find下),找出一个节点上的文件后复制到各个节点上。
2.集群有两种模式,普通和镜像模式。
普通模式:
对于Queue来说,消息实体只存在于其中一个节点,A、B两个节点仅有相同的元数据,即队列结构。
当消息进入A节点的Queue中后,consumer从B节点拉取时,RabbitMQ会临时在A、B间进行消息传输,把A中的消息实体取出并经过B发送给consumer。
所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连A或B,出口总在A,会产生瓶颈。
该模式存在一个问题就是当A节点故障后,B节点无法取到A节点中还未消费的消息实体。
如果做了消息持久化,那么得等A节点恢复,然后才可被消费;如果没有持久化的话,数据就会丢失掉。
镜像模式:
该模式解决了上述问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取。
该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。
2.2 集群节点
集群中有两种节点:
- 内存节点:只保存状态到内存(一个例外的情况是:持久的queue的持久内容将被保存到disk)
- 磁盘节点:保存状态到内存和磁盘
内存节点虽然不写入磁盘,但是它执行比磁盘节点要好。集群中,只需要一个磁盘节点来保存状态就足够了。
如果集群中只有内存节点,那么不能停止它们,否则所有的状态、消息等都会丢失。
详细可见链接。
2.3 负载均衡器
关于负载均衡器,商业的比如F5的BIG-IP,Radware的AppDirector,是硬件架构的产品,可以实现很高的处理能力。但这些产品昂贵的价格会让人止步,所以我们还有软件负载均衡方案--互联网公司常用的软件LB一般有LVS、HAProxy、Nginx等。LVS是一个内核层的产品,主要在第四层负责数据包转发,使用较复杂。HAProxy和Nginx是应用层的产品,但Nginx主要用于处理HTTP,所以这里选择HAProxy作为RabbitMQ前端的LB。
因为当前业务主要是实现RabbitMQ前端的LB,所以只配置和RabbitMQ相关的参数:
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
listen rabbitmq_cluster
bind *:5671
mode tcp
balance roundrobin
server rqslave1 172.16.3.107:5672 check inter 2000 rise 2 fall 3
server rqslave2 172.16.3.108:5672 check inter 2000 rise 2 fall 3
rqslave1 是172.16.3.107:5672上的节点名称,请严格对应。
check为健康检查指令。
inter 2000表示检察时间间隔为2000毫秒。
rise 2表示检查成功两次即将其标识为可用。
fall 3表示检查失败三次即将其标识为不可用
注:
负载均衡器会绑定5671端口,且轮询我们的两个节点172.16.3.107、172.16.3.108的5672端口;
这样磁盘节点出了故障也不会影响,除非同时出故障。
访问的端口需要调整为haproxy所在的机器ip加绑定的端口号,例如172.16.3.108:5761。
2.4 配置策略
使用Rabbit镜像功能,需要基于rabbitmq策略来实现,策略是用来控制和修改集群范围中某个vhost队列行为和Exchange行为。
在cluster中任意节点启用策略,策略会自动同步到集群节点。
# rabbitmqctl set_policy ha-allqueue "^" '{"ha-mode":"all"}'
这行命令在vhost名称为hrsystem创建了一个策略,策略名称为ha-allqueue,策略模式为 all 即复制到所有节点,包含新增节点,策略中正则表达式 “^” 表示所有匹配的队列名称。
官方set_policy说明参见。
3. 总结
1. 设计架构可以如下:在一个集群里,有4台机器,其中1台使用磁盘模式,另2台使用内存模式。
2台内存模式的节点,无疑速度更快,因此客户端(consumer、producer)连接访问它们。
而磁盘模式的节点,由于磁盘IO相对较慢,因此仅作数据备份使用,另外一台作为反向代理。
2. 作者在搭建的过程中遇到了很多问题,但回头看看,静下心来大多是可以避免的;
心平气和地,一步一步地,林深见鹿,海蓝逢鲸。
网友评论