docker-compose部署rabbitmq集群

1、集群分类
RabbitMQ的是基于Erlang语言编写,而Erlang又是一个面向并发的语言,天然支持集群模式。
RabbitMQ的集群以下分类:
标准集群:是一种分布式集群,将队列分散到集群的各个节点,从而提高整个集群的并发能力。
镜像集群:是一种主从集群,标准集群的基础上,添加了主从备份功能(非强一致性),提高集群的数据可用性。
仲裁队列: 是3.8版本以后才有的新功能,用来替代镜像集群,也是一种主从集群,主从同步基于Raft协议,强一致。
镜像集群虽然支持主从,但主从同步并不是强一致的,某些情况下可能有数据丢失的风险。因此在RabbitMQ的3.8版本以后,推出了新的功能:仲裁队列来代替镜像集群,底层采用Raft协议确保主从的数据一致性。
1.1、标准集群
标准模式集群不进行数据同步。
会在集群的各个节点间共享部分数据,包括:交换机、队列元信息。不包含队列中的消息。
当访问集群某节点时,如果队列不在该节点,会从数据所在节点传递到当前节点并返回。
队列所在节点宕机,队列中的消息就会丢失。
比如:我们有2个MQ:mq1和mq2,如果你的消息在mq1,而你连接到了mq2,那么mq2会去mq1拉取消息,然后返回给你。如果mq1宕机,消息就会丢失。
docker-compose部署rabbitmq集群_第1张图片
1.2、镜像集群
镜像集群:本质是主从模式,具备下面的特征:

交换机、队列、队列中的消息会在各个mq的镜像节点之间同步备份。
创建队列的节点被称为该队列的主节点, 备份到的其它节点叫做该队列的镜像节点。
一个队列的主节点可能是另一个队列的镜像节点。
所有操作都是主节点完成,然后同步给镜像节点。
主节点宕机后,镜像节点会替代成新的主节点。
docker-compose部署rabbitmq集群_第2张图片
1.3、仲裁队列
​ 仲裁队列是3.8版本以后才有的新功能,用来替代镜像队列,具备下列特征:
与镜像队列一样,都是主从模式,支持主从数据同步
使用非常简单,没有复杂的配置
主从同步基于Raft协议,强一致
2、集群部署
2.1、节点说明
在rabbitmq集群部署时,集群中的节点标示默认都是:rabbit@[hostname]
计划部署3节点的mq集群,,三个节点在不同机器上,为了方便主机名称分别为mq1、mq2、mq3,节点也进行相应的映射;
15672映射为8081 、8082 、8083,5672映射为8071、8072、8073;如下:

1 1 1

放了方便演示,以下部署都在同一台服务器中进行,因为端口都做了映射不会出现冲突
2.2、标准集群模式
2.2.1.创建目录

mkdir -p /root/docker/rabbitmq-cluster/mq1[2|3]

2.2.2.设置hosts
注意:如果是同一台机器上,搭建不同的docker实例,则不进行设置。
分别在三台不同的机器上编辑hosts文件

# mq1
vim  /root/docker/rabbitmq-cluster/mq1/hosts
# mq2
vim  /root/docker/rabbitmq-cluster/mq2/hosts
# mq3
vim  /root/docker/rabbitmq-cluster/mq3/hosts

内容都如下:

# 配置hosts映射
111.229.160.173   mq1
111.229.160.174   mq2
111.229.160.175   mq3

2.2.3.设置cookie:
RabbitMQ底层依赖于Erlang,而Erlang虚拟机就是一个面向分布式的语言,默认就支持集群模式。集群模式中的每个RabbitMQ 节点使用 cookie 来确定它们是否被允许相互通信。
要使两个节点能够通信,它们必须具有相同的共享密钥,称为Erlang cookie,cookie 是一串最多 255 个字符的任意字母数字字符。
每个集群节点必须具有相同的 cookie,实例之间也需要它来相互通信。

# Cookie配置
vim /root/docker/rabbitmq-cluster/mq1/.erlang.cookie
# 配置内容-cookie值(任意值)
UDCUIBNPHPETOIURAHRF
# 修改cookie文件的权限
chmod 600 /root/docker/rabbitmq-cluster/mq1/.erlang.cookie

2.2.4、设置配置文件

# mq1
vim /root/docker/rabbitmq-cluster/mq1/rabbitmq.conf

内容都如下:

# 配置内容
loopback_users.guest = false
listeners.tcp.default = 5672
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
cluster_formation.classic_config.nodes.1 = rabbit@mq1
cluster_formation.classic_config.nodes.2 = rabbit@mq2
cluster_formation.classic_config.nodes.3 = rabbit@mq3

注意rabbit@xxx为每个rabbitmq实例的hostname,和启动容器时的–hostname值一致
2.2.5、拷贝目录
如果有多台服务器,则将配置好的一个rabbitmq节点的文件,拷贝到其他服务器上;如果是一台服务器,则拷贝到不同的目录下即可。

# 将mq1目录拷贝为mq2、mq3
cp /root/docker/rabbitmq-cluster/mq1 /root/docker/rabbitmq-cluster/mq2 -r
cp /root/docker/rabbitmq-cluster/mq1 /root/docker/rabbitmq-cluster/mq3 -r

2.2.6、启动容器
注意:如果是同一台机器上,搭建不同的docker实例,则直接创建同一个网络环境

#创建网络
docker network create mq-net

以下使用docker-compose部署服务

version: '3'
services:
  
  rabbitmq1:
    restart: always
    image: rabbitmq:3.8.5-management
    container_name: rabbitmq1
    hostname: rabbitmq1
    ports:
      - 8071:5672
      - 8081:15672
    environment:
      TZ: Asia/Shanghai
      RABBITMQ_DEFAULT_USER: rabbit   #自定义登录账号
      RABBITMQ_DEFAULT_PASS: 123456 #自定义登录密码
    volumes:
      - /root/docker/rabbitmq-cluster/mq1/data:/var/lib/rabbitmq
      - /root/docker/rabbitmq-cluster/mq1/conf/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
      - /root/docker/rabbitmq-cluster/mq1/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie

  rabbitmq2:
    restart: always
    image: rabbitmq:3.8.5-management
    container_name: rabbitmq2
    hostname: rabbitmq2
    ports:
      - 8072:5672
      - 8082:15672
    environment:
      TZ: Asia/Shanghai
      RABBITMQ_DEFAULT_USER: rabbit   #自定义登录账号
      RABBITMQ_DEFAULT_PASS: 123456 #自定义登录密码
    volumes:
      - /root/docker/rabbitmq-cluster/mq2/data:/var/lib/rabbitmq
      - /root/docker/rabbitmq-cluster/mq2/conf/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
      - /root/docker/rabbitmq-cluster/mq2/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie

  rabbitmq3:
    restart: always
    image: rabbitmq:3.8.5-management
    container_name: rabbitmq3
    hostname: rabbitmq3
    ports:
      - 8073:5672
      - 8083:15672
    environment:
      TZ: Asia/Shanghai
      RABBITMQ_DEFAULT_USER: rabbit   #自定义登录账号
      RABBITMQ_DEFAULT_PASS: 123456 #自定义登录密码
    volumes:
      - /root/docker/rabbitmq-cluster/mq3/data:/var/lib/rabbitmq
      - /root/docker/rabbitmq-cluster/mq3/conf/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
      - /root/docker/rabbitmq-cluster/mq3/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie

启动容器

# 如果后面没有带容器名就是启动全部
docker-compose -f docker-compose.yml up -d

结果:
在这里插入图片描述
2.2.7、集群测试
控制台管理地址:http://xxx.xxx.xxx.xxx:8081|8082|8083,访问任意节点,所看到的信息是一致的;
为了更加方便的管理,可以通过nginx配置负载均衡,实现web页面的统一访问地址。
docker-compose部署rabbitmq集群_第3张图片
2.2.7.1.连通性测试
在mq1这个节点上添加一个队列:
docker-compose部署rabbitmq集群_第4张图片
分别访问mq2和mq3两个控制台也都能看到:
docker-compose部署rabbitmq集群_第5张图片
2.2.7.2.数据共享测试
进入mq1节点发送一台消息:
在这里插入图片描述
docker-compose部署rabbitmq集群_第6张图片
分别访问mq2和mq3两个控制台也能看到消息:
docker-compose部署rabbitmq集群_第7张图片
2.2.7.3.可用性测试
让节点mq1宕机:

docker stop mq1

分别访问mq2和mq3两个控制台,看到simple.mq1已不可用:
docker-compose部署rabbitmq集群_第8张图片
说明mq1的数据并没有拷贝到mq2和mq3。
2.3、镜像集群模式
在标准集群模式下,一旦创建队列的主机宕机,队列就会不可用。不具备高可用能力。如果要解决这个问题,必须使用镜像集群方案。

镜像模式下,创建队列的节点被称为该队列的主节点,队列还会拷贝到集群中的其它节点,也叫做该队列的镜像节点。

队列的所有操作都在主节点上完成,镜像节点仅仅起到备份数据作用。如果是从节点接收到操作请求,也会路由到主节点去完成。
当主节点接收到消费者的ACK时,所有镜像都会删除节点中的数据。

镜像模式的配置有3种模式:
docker-compose部署rabbitmq集群_第9张图片
镜像集群模式是对队列的一种主从复制操作,需要通过一定规则对指定的队列实现主从同步操作
2.3.1、exactly模式

rabbitmqctl set_policy ha-exactly "^exactly\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'

rabbitmqctl set_policy:固定写法
ha-exactly:策略名称,自定义
“^exactly.”:匹配队列的正则表达式,符合命名规则的队列才生效,这里是任何以lhz.开头的队列名称
‘{“ha-mode”:“exactly”,“ha-params”:2,“ha-sync-mode”:“automatic”}’: 策略内容
“ha-mode”:“exactly”:策略模式,此处是exactly模式,指定副本数量
“ha-params”:2:策略参数,这里是2,就是副本数量为2,1主1镜像
“ha-sync-mode”:“automatic”:同步策略,默认是manual,即新加入的镜像节点不会同步旧的消息。如果设置为automatic,则新加入的镜像节点会把主节点中所有消息都同步,会带来额外的网络开销
2.3.2、all模式

rabbitmqctl set_policy ha-all "^all\." '{"ha-mode":"all"}'

ha-all:策略名称,自定义
“^all.”:匹配所有以all.开头的队列名
‘{“ha-mode”:“all”}’:策略内容
“ha-mode”:“all”:策略模式,此处是all模式,即所有节点都会称为镜像节点
2.3.3、nodes模式

rabbitmqctl set_policy ha-nodes "^nodes\." '{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}'

rabbitmqctl set_policy:固定写法
ha-nodes:策略名称,自定义
“^nodes.”:匹配队列的正则表达式,符合命名规则的队列才生效,这里是任何以nodes.开头的队列名称
‘{“ha-mode”:“nodes”,“ha-params”:[“rabbit@nodeA”, “rabbit@nodeB”]}’: 策略内容
“ha-mode”:“nodes”:策略模式,此处是nodes模式
“ha-params”:[“rabbit@mq1”, “rabbit@mq2”]:策略参数,这里指定副本所在节点名称
2.3.4、测试
使用exactly,设置镜像数为(N / 2 +1)。
使用exactly模式的镜像,因为集群节点数量为3,因此镜像数量就设置为2.
对任意节点操作,被操作的节点会视为主节点
创建命令:

docker exec -it mq1 rabbitmqctl set_policy exactly-test "^test\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'

exactly-test:模式名称
“^test.”:正则匹配,test开头的队列
2.3.4.1、连通性测试
在mq1节点,创建队列:test.mq1
docker-compose部署rabbitmq集群_第10张图片
在任意一个mq控制台查看队列:
在这里插入图片描述
2.3.4.2、数据共享测试
通过test.queue发送一条消息:
docker-compose部署rabbitmq集群_第11张图片
然后在任意节点控制台查看消息:
docker-compose部署rabbitmq集群_第12张图片
2.3.4.3、高可用测试
让test.queue队列所在的节点mq1宕机

docker stop mq1

查看集群状态:
docker-compose部署rabbitmq集群_第13张图片
查看队列状态:
docker-compose部署rabbitmq集群_第14张图片
发现test.queue队列,依然是健康的!并且其主节点切换到了rabbit@mq3上
2.4、仲裁队列模式
在任意控制台添加一个队列,一定要选择队列类型为Quorum类型
docker-compose部署rabbitmq集群_第15张图片
在任意控制台查看队列:
docker-compose部署rabbitmq集群_第16张图片
可以看到,仲裁队列的 + 2字样,代表这个队列有2个镜像节点
3、集群扩容
启动一个新的MQ容器

# 拷贝目录
cp /root/docker/rabbitmq-cluster/mq1 /root/docker/rabbitmq-cluster/mq4 -r
# 修改docker-compose.yml,添加一个服务实例
rabbitmq4:
    restart: always
    image: rabbitmq:3.8.5-management
    container_name: rabbitmq4
    hostname: rabbitmq4
    ports:
      - 8074:5672
      - 8084:15672
    environment:
      TZ: Asia/Shanghai
      RABBITMQ_DEFAULT_USER: rabbit   #自定义登录账号
      RABBITMQ_DEFAULT_PASS: 123456 #自定义登录密码
    volumes:
      - /root/docker/rabbitmq-cluster/mq4/data:/var/lib/rabbitmq
      - /root/docker/rabbitmq-cluster/mq4/conf/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
      - /root/docker/rabbitmq-cluster/mq4/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie
#启动容器
docker-compose -f docker-compose.yml up -d rabbitmq4
#进入容器控制台
docker exec -it mq4 bash
#停止mq对外访问
rabbitmqctl stop_app
#重置RabbitMQ中的数据
rabbitmqctl reset
#mq4加入mq1
rabbitmqctl join_cluster rabbit@mq1
#再次启动mq进程
rabbitmqctl start_app

docker-compose部署rabbitmq集群_第17张图片
4、SprngBoot集群配置

spring:
  application:
    name: rabbit
  # rabbitmq配置
  rabbitmq:
    # 集群配置
    addresses: 127.0.0.1:8071, 127.0.0.1:8072, 127.0.0.1:8073
    username: admin
    password: admin
    virtual-host: /

5、集群高可用
集群高可用有两种方式
1.通过Nginx代理转发
2.haproxy
以下通过haproxy作为集群高可用的代理

安装haproxy
yum install haproxy
#2、配置haproxy.cfg文件   具体参照 如下 5.1 配置HAProxy
vim  /etc/haproxy/haproxy.cfg
#3、启动haproxy
systemctl start haproxy
#4、查看haproxy进程状态
systemctl status haproxy.service
#状态如下说明 已经启动成功 Active: active (running)
#访问如下地址对mq节点进行监控
http://服务器IP:1080/haproxy_stats
#代码中访问mq集群地址,则变为访问haproxy地址:5672

docker-compose部署rabbitmq集群_第18张图片
5.1 配置HAProxy
配置文件路径:/etc/haproxy/haproxy.cfg

#---------------------------------------------------------------------
# Example configuration for a possible web application.  See the
# full configuration options online.
#
#   http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    #
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    #
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
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

#对MQ集群进行监听
listen rabbitmq_cluster 192.168.23.146:5671
	option tcplog
	mode tcp 
	option  clitcpka
	timeout connect 1s 
	timeout client  10s
	timeout server  10s
	balance roundrobin
	server node1  192.168.23.146:5681 check inter 5s rise 2 fall 3  
    server node2  192.168.23.146:5682 check inter 5s rise 2 fall 3
    server node3  192.168.23.146:5683 check inter 5s rise 2 fall 3

#开启haproxy监控服务	
listen http_front
	bind 192.168.23.146:1080
	stats refresh 30s
	stats uri /haproxy_stats
	stats auth admin:admin

haproxy.cfg配置详解

listen rabbitmg cluster
bind 0.0.0.0:5672#通过5672对M1, M2进行映射
option tcplog #记录tcp连接的状态和时间
mode tcp#四层协议代理,即对TCP协议转发
option clitcpka #开启TCP的Keep Alive. (长连接模式)
timeout connect 1s #haproxy与mq建立连接的超时时间
timeout client 10s#客户端与haproxy最大空闲时间。
timeout server 10s #服务器与haproxy最大空闲时间
balance roundrobin #采用轮询转发消息
#每5秒发送一次心跳包,如连续两次有响应则代表状态良好。
#如连续三次没有响应,则视为服务故障,该节点将被剔除。
server node1 192.168.132.137:5672 check inter 5s rise 2 fall 3
server node2192.168.132.139:5672 check inter 5s rise 2 fall 3
listen http front
#监听端口
bind 0.0.0.0:1080
#统计页面自动刷新时间stats refresh 30s
#统计页面url
stats uri /haproxy?stats
#指定HAproxy访问用户名和密码设置
stats auth admin:admin

你可能感兴趣的:(rabbitmq,java-rabbitmq,rabbitmq,docker)