- 消息中间件RabbitMQ,一般以集群方式部署,主要提供消息的接受和发送,实现各微服务之间的消息异步。以下将介绍RabbitMQ+HA方式进行部署。
1、原理介绍
-
RabbitMQ是依据erlang的分布式特性(RabbitMQ底层是通过Erlang架构来实现的,所以rabbitmqctl会启动Erlang节点,并基于Erlang节点来使用Erlang系统连接RabbitMQ节点,在连接过程中需要正确的Erlang Cookie和节点名称,Erlang节点通过交换Erlang Cookie以获得认证)来实现的,所以部署Rabbitmq分布式集群时要先安装Erlang,并把其中一个服务的cookie复制到另外的节点。
-
RabbitMQ集群中,各个RabbitMQ为对等节点,即每个节点均提供给客户端连接,进行消息的接收和发送。节点分为内存节点和磁盘节点,一般的,均应建立为磁盘节点,为了防止机器重启后的消息消失;
-
RabbitMQ的Cluster集群模式一般分为两种,普通模式和镜像模式。消息队列通过RabbitMQ HA镜像队列进行消息队列实体复制。
- 普通模式下,以两个节点(rabbit01、rabbit02)为例来进行说明。对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列的结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01、rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer。所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。
- 镜像模式下,将需要消费的队列变为镜像队列,存在于多个节点,这样就可以实现RabbitMQ的HA高可用性。作用就是消息实体会主动在镜像节点之间实现同步,而不是像普通模式那样,在consumer消费数据时临时读取。缺点就是,集群内部的同步通讯会占用大量的网络带宽。
2、部署 RabbitMQ Cluster
1、rabbitmq 有 3 种模式,但集群模式是 2 种
- 单一模式:即单机情况不做集群,就单独运行一个 rabbitmq 而已。
- 普通模式:默认模式,以两个节点(rabbit01、rabbit02)为例来进行说明。对于 Queue 来说,消息实体只存在于其中一个节点 rabbit01(或者 rabbit02),rabbit01 和 rabbit02 两个节点仅有相同的元数据,即队列的结构。当消息进入 rabbit01 节点的 Queue 后,consumer 从 rabbit02 节点消费时,RabbitMQ 会临时在 rabbit01、rabbit02 间进行消息传输,把 A 中的消息实体取出并经过 B 发送给 consumer。所以 consumer 应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理 Queue。否则无论 consumer 连 rabbit01 或 rabbit02,出口总在 rabbit01,会产生瓶颈。当 rabbit01 节点故障后,rabbit02 节点无法取到 rabbit01 节点中还未消费的消息实体。如果做了消息持久化,那么得等 rabbit01 节点恢复,然后才可被消费;如果没有持久化的话,就会产生消息丢失的现象。
- 镜像模式: 把需要的队列做成镜像队列,存在与多个节点属于 RabbitMQ 的 HA 方案。该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用。
2、环境准备
3台centos7操作系统,ip分别为:
192.168.122.124
192.168.122.66
192.168.122.122
3、修改 hosts 文件 (3 台)
[root@rabbitmq1 ~]# vim /etc/hosts
192.168.122.124 rabbitmq1
192.168.122.65 rabbitmq2
192.168.122.122 rabbitmq3
4、保证 3 台能 ping 通 (3 台)
[root@rabbitmq1 ~]# ping rabbitmq1
PING rabbitmq1 (192.168.122.124) 56(84) bytes of data.
64 bytes from rabbitmq01 (192.168.122.124): icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from rabbitmq01 (192.168.122.124): icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from rabbitmq01 (192.168.122.124): icmp_seq=3 ttl=64 time=0.052 ms
[root@rabbitmq1 ~]# ping rabbitmq2
PING rabbitmq2 (192.168.122.66) 56(84) bytes of data.
64 bytes from rabbitmq02 (192.168.122.66): icmp_seq=1 ttl=64 time=0.595 ms
64 bytes from rabbitmq02 (192.168.122.66): icmp_seq=2 ttl=64 time=0.536 ms
64 bytes from rabbitmq02 (192.168.122.66): icmp_seq=3 ttl=64 time=0.453 ms
64 bytes from rabbitmq02 (192.168.122.66): icmp_seq=4 ttl=64 time=0.478 ms
[root@rabbitmq1 ~]# ping rabbitmq3
PING rabbitmq3 (192.168.122.122) 56(84) bytes of data.
64 bytes from rabbitmq03 (192.168.122.122): icmp_seq=1 ttl=64 time=0.800 ms
64 bytes from rabbitmq03 (192.168.122.122): icmp_seq=2 ttl=64 time=0.470 ms
64 bytes from rabbitmq03 (192.