1.rabbitmq集群
单机多实例的集群测试
10.5.16.222上
$ RABBITMQ_NODE_PORT=5672 RABBITMQ_NODENAME=rabbit1 rabbitmq-server -detached
$ RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=hare1 rabbitmq-server -detached
$ rabbitmqctl -n hare stop_app
$ rabbitmqctl -n hare join_cluster rabbit@`beta`
$ rabbitmqctl -n hare start_app
停掉
root@beta:~# rabbitmqctl -n hare1 stop
Stopping and halting node hare1@beta ...
...done.
root@beta:~# rabbitmqctl -n rabbit1 cluster_status
Cluster status of node rabbit1@beta ...
[{nodes,[{disc,[hare1@beta,rabbit1@beta]}]},
{running_nodes,[rabbit1@beta]},
{partitions,[]}]
...done.
重新启动hare1
root@beta:~# rabbitmqctl -n hare1 cluster_status
Cluster status of node hare1@beta ...
[{nodes,[{disc,[hare1@beta,rabbit1@beta]}]},
{running_nodes,[rabbit1@beta,hare1@beta]},
{partitions,[]}]
...done.
单机简单集群搭建完毕,使用消息发送与接收测试,增加节点客户端消息接收器需重启,删除节点不需重新配置,使用镜像队列可防止消息单节点丢失,但性能会打折扣。
减少客户端配置可以使用dns服务器来代替ip+端口,也可以使用下一节调研的负载均衡器。
2.负载均衡(可选)
于是在另外一台128上搭建tcp负载均衡器
10.5.16.128
apt安装haproxy
配置 /etc/haproxy/haproxy.cfg:
listen rabbitmq 0.0.0.0:56720
mode tcp
balance roundrobin
option tcpka
server rabbit1 10.5.16.222:5672 check inter 5000 rise 2fall 5
server hare1 10.5.16.222:5673 check inter 5000 rise 2fall 5
客户端配置到haproxy所在服务器的地址与监听端口
stats uri /haproxy-stats
stats realm Haproxy\ statistics
stats auth franklin:111111
状态监听http://XXX/haproxy-stats
3.镜像队列
spring 镜像队列配置
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" reply-queue-arguments="haArgs" />
<rabbit:queue auto-delete="true" durable="false"id="mailQueue"
name="#{config.project.mailQueueName}" queue-arguments="haArgs"></rabbit:queue>
<rabbit:queue-arguments id="haArgs">
<entry key="x-ha-policy" value="all" />
</rabbit:queue-arguments>
4.额外参考说明
不做镜像队列的话,节点down掉则必须等他回复,不然消息就丢失了。master节点退出集群会选一个slave作为master,那么要是不幸选中了一个刚刚加入集群的节点怎么办?不就丢消息了么?放心RabbitMQ会维护节点的状态是否已经同步,使用rabbitmqctl的synchronised_slave_pids参数,就可以查看状态. 对于publish,客户端任意连接集群的一个节点,转发给创建queue的节点存储消息的所有信息;
对于consumer,客户端任意连接集群中的一个节点,如果数据不在该节点中,则从存储该消息data的节点拉取。可见当存储有queue内容的节点失效后,只要等待该节点恢复后,queue中存在的消息才可以获取消费的到。显然增加集群的节点,可以提高整个集群的吞吐量,但是在高可用方面要稍微差一些
mirror queue是为rabbitMQ高可用的一种方案,相对于普通的集群方案来讲,queue中的消息每个节点都会存在一份copy,这个在单个节点失效的情况下,整个集群仍旧可以提供服务。但是由于数据需要在多个节点复制,在增加可用性的同时,系统的吞吐量会有所下降。
在实现机制上,mirror queue内部实现了一套选举算法,有一个master和多个slave,queue中的消息以master为主,对于publish,可以选择任意一个节点进行连接,rabbitmq内部若该节点不是master,则转发给master,master向其他slave节点发送该消息,后进行消息本地化处理,并组播复制消息到其他节点存储,对于consumer,可以选择任意一个节点进行连接,消费的请求会转发给master,为保证消息的可靠性,consumer需要进行ack确认,master收到ack后,才会删除消息,ack消息会同步(默认异步)到其他各个节点,进行slave节点删除消息。若master节点失效,则mirror queue会自动选举出一个节点(slave中消息队列最长者)作为master,作为消息消费的基准参考;在这种情况下可能存在ack消息未同步到所有节点的情况(默认异步),若slave节点失效,mirror queue集群中其他节点的状态无需改变。