Rabbitmq集群

一、Rabbitmq集群模式

1.1 rabbitmq介绍

RabbitMQ 是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息。

官网 :

1.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方案。该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用;

1.3 rabbitmq端口
4369      erlang发现口
5672      client端通信口
15672     管理界面ui端口
25672     server间内部通信口

二、Rabbitmq集群搭建

2.1 节点规划
主机名 IP 配置
rabbit01 10.0.0.11 4c8G
rabbit02 10.0.0.12 4c8G
rabbit03 10.0.0.13 4c8G
2.2 初始化
# 定义主机名
hostnamectl set-hostname rabbit01
hostnamectl set-hostname rabbit02
hostnamectl set-hostname rabbit03
# 定义解析
cat >> /etc/hosts <<eof
rabbit01 10.0.0.11
rabbit02 10.0.0.12
rabbit03 10.0.0.13
eof
# 确认组件
[root@rabbit01 ~]# docker --version
Docker version 1.13.1, build 7d71120/1.13.1
[root@rabbit01 bin]# docker-compose --version
docker-compose version 1.29.1, build c34c88b2
2.3 启动服务
# 创建数据目录
mkdir -p rabbitmq/data
vim rabbitmq/docker-compose.yml
# rabbit01
version: '3.1'
services:
  rabbitmq:
    image: daocloud.io/library/rabbitmq:3.7.27-management-alpine
    container_name: rabbit01
    restart: always
    hostname: rabbitmq
    extra_hosts:
      - "rabbit01:10.0.0.11"
      - "rabbit02:10.0.0.12"
      - "rabbit03:10.0.0.13"
    ports:
      - 15672:15672
      - 5672:5672
      - 25672:25672
      - 4369:4369
    volumes:
      - ./data:/var/lib/rabbitmq
    environment:
      - RABBITMQ_DEFAULT_USER=mqadmin
      - RABBITMQ_DEFAULT_PASS=mq2021
      - RABBITMQ_ERLANG_COOKIE=rst2021
# rabbit02
version: '3.1'
services:
  rabbitmq:
    image: daocloud.io/library/rabbitmq:3.7.27-management-alpine
    container_name: rabbitmq
    restart: always
    hostname: rabbit02
    extra_hosts:
      - "rabbit01:10.0.0.11"
      - "rabbit02:10.0.0.12"
      - "rabbit03:10.0.0.13"
    ports:
      - 15672:15672
      - 5672:5672
      - 25672:25672
      - 4369:4369
    volumes:
      - ./data:/var/lib/rabbitmq
    environment:
      - RABBITMQ_DEFAULT_USER=mqadmin
      - RABBITMQ_DEFAULT_PASS=mq2021
      - RABBITMQ_ERLANG_COOKIE=rst2021
# rabbit03
version: '3.1'
services:
  rabbitmq:
    image: daocloud.io/library/rabbitmq:3.7.27-management-alpine
    container_name: rabbit03
    restart: always
    hostname: rabbitmq
    extra_hosts:
      - "rabbit01:10.0.0.11"
      - "rabbit02:10.0.0.12"
      - "rabbit03:10.0.0.13"
    ports:
      - 15672:15672
      - 5672:5672
      - 25672:25672
      - 4369:4369
    volumes:
      - ./data:/var/lib/rabbitmq
    environment:
      - RABBITMQ_DEFAULT_USER=mqadmin
      - RABBITMQ_DEFAULT_PASS=mq2021
      - RABBITMQ_ERLANG_COOKIE=rst2021
cd rabbitmq;docker-compose up -d
2.5 加入集群

在rabbit02和rabbit03两个节点上执行如下操作,作为slave加入到集群中,作为内存节点加入;

docker exec -it rabbitmq /bin/bash                # 进入容器
rabbitmqctl stop_app                              # 关闭应用
rabbitmqctl reset                                 # 清空队列
rabbitmqctl join_cluster --ram rabbit@rabbit01  # 加入集群
rabbitmqctl start_app                             # 启动应用

执行完毕后,在任一机器的15672端口查看,均可以看到三个节点;



磁盘节点和内存节点的区别在于: 磁盘节点除了内存中会存运行时状态信息(队列信息,集群信息,用户信息等),磁盘中也会存运行时状态信息。消息的持久化只与delivery-mode有关,不管是磁盘节点还是内存节点,只要delivery-mode标记为2,这条消息就会写入磁盘;

虽然队列只会存在任意的一个节点之中,但是各个节点的元数据会进行同步,所以我们能够在任一节点中看到所有的队列信息。但我们生产或者消费的队列不在连接的节点上时,则会根据元数据信息将消息进行转发;

普通集群模式不具备高可用,由于普通集群模式只同步了各个节点的元数据(队列名,路由器等信息),并没有在每个节点上创建相同的队列,所以当某个节点down掉后,该节点上创建的队列都不可用了;

2.6 镜像集群

镜像集群模式是在普通集群模式的基础上,指定策略就行了;

# 在集群内的任一机器指定策略
docker exec -it rabbitmq /bin/bash
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
rabbitmqctl  cluster_status

执行完成后会发现,每个节点的队列上会有 ha-all 的策略标识;



三、rabbitmq集群管理

3.1 删除节点
# 将从节点从集群中剔除,在主节点上执行剔除命令
rabbitmqctl -n rabbit@rabbitmq01 forget_cluster_node rabbit@rabbitmq02
3.2 重新加入
# 重新加入集群的节点中残留有旧的信息,先清空旧的信息,再加入集群
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
3.3 集群恢复

停掉集群中的一台机器,然后再重启这台机器,发现并未自动的加入到集群中,原因是出现了网络分区现象。

解决方法 :修改/etc/rabbitmq/rabbitmq.conf文件,配置cluster_partition_handling为autoheal ;

cluster_partition_handling=autoheal