一.进行集群的目的
集群主要用于实现高可用与负载均衡。
高可用: 如果集群中的某些MQ服务器不可用,客户端还可以连接到其他MQ服务器。不至于影响业务。
负载均衡:在高并发场景下,单台MQ服务器能处理的消息有限,可以分发给多台服务器。减少消息延迟。
二.RabbitMQ集群
1.RabbitMQ如何支持集群
因为Erlang天生具备分布式的特点,所以RabbitMQ天然支持集群,不需要通过引入ZK来实现数据同步。RabbitMQ通过.erlang.cookie(默认路径:/var/lib/rabbitmq)来验证身份,需要所有节点上保持一致。服务端端口5672,UI的端口15672,集群的端口25672。集群通过25672端口两两通信,需要开放防火墙的端口.
2.RabbitMQ的节点类型
1) 磁盘节点
将元数据(包括名字属性、交换机的类型名字属性、绑定、vhost)放在磁盘中。未指定类型的情况下,默认为磁盘节点。集群中至少需要一个磁盘节点来持久化元数据,否则全部内存节点崩溃就无从同步元数据
2)内存节点
将元数据放在内存中。
ps:持久化的消息,会同时存放在内存和磁盘。我们一般把应用连接到内存节点(读写快)。磁盘节点用来备份。
2.RabbitMQ集群的配置步骤
1)配置host以便相互通信
2)同步erlang.cookie
3)加入集群(join cluster命令)
3.RabbitMQ的集群模式
1)普通集群模式
普通集权模式下,不同的节点之间只会相互同步元数据(交换机、队列、绑定关系、Vhost的定义),而不会同步消息。
比如队列1的消息只存储在节点1上,节点2和节点3同步队列1的定义,但是没有同步消息。加入生产者连接的是节点3,要将消息通过交换机A路由到队列1,最终消息还是会转发到节点1存储。同类,消费者连接节点2,要从队列1上拉取消息,消息会从节点1转发到节点2,其他节点起到一个路由的作用。
ps:这就是一个分片思想,主要是出于存储和同步数据的网络开销的考虑,如果所有节点都存储相同的数据,就无法达到线性的增加性能和存储容量的目的(堆机器)。但存在若存储节点失效,整个队列不可用。
2)镜像集群
镜像队列模式下,消息内容会在镜像节点间同步,可用性更高,不过相对,系统性能会降低,节点过多时同步的代价比较大
4.高可用(以HAProxy+Keepalived)
1)HAProxy作用
集群搭建完成后会有,会有多个内存节点。我们如果在客户端代码中制定策略选择生产者和消费者应该连接到的内存节点。需要修改的代码可能较多,也比较麻烦。此时需要引入负载均衡组件(例如HAProxy,Nignx,LVS),由负载的组件来进行路由。客户端只需连接都负载组件的IP地址就可以了。
2)Keepalived作用
负载组件也会挂掉,客户端就无法连接到任意一台MQ服务器,所以负载也需要做负载。但如何找负载呢?显然再继续加负载就会陷入死循环了。因此我们需要另外一个组件Keepalived。
a.本身具有路由(负载)功能,可以监控集群中节点的状态(比如监控HAProxy),如果某个节点出现异常或者发生故障,进行剔除。
b.为了提高可用性,可以部署多个服务,但只有一个自动选举出来的MASTER服务器(主路由器),通过广播心跳消息实现。
c.MASTER服务器对外提供一个虚拟IP,提供各种网络功能。谁抢占到虚拟IP,谁对外提供网络服务,应用端只需连接到一个IP就可以
5.配置教程:https://gper.club/articles/7e7e7f7ff3g5bgc5g6c