RabbitMQ集群基本知识
集群有两种节点类型,一种是磁盘节点(Disc Node),另一种是内存节点(Ram Node)集群通过25672端口通信,需要开放防火墙的端口常见的集群架构模式有:普通集群,镜像队列,多活模式(不常用),远程模式(不常用)等每个节点的/var/lib/rabbitmq/.erlang.cookie文件必须一致否则无法构成集群RabbitMQ是不能在广域网上搭建集群的,除非使用federation或者shovel等插件(一般在同一个机房做集群)
RabbitMQ的两种节点类型介绍
磁盘节点将元数据(队列名字属性,交换机的类型名字属性,绑定关系,vhost)放在磁盘中内存节点将元数据放在磁盘中内存节点会将磁盘节点的地址存放在磁盘(不然重启后就没有办法同步数据了)。 如果是持久化的消息,会同时存放在内存和磁盘集群中至少需要一个磁盘节点用来持久化元数据,否则全部内存节点崩溃就无从同步元数据了,节点加入到集群中默认是磁盘节点(可以在加入集群的时候指定为内存节点)我们一般把应用连接到内存节点因为读写快,磁盘节点用来备份数据
普通集群
普通集群搭建步骤
配置主机名让所有节点的erlang.cookie文件内容保持一致一个节点作为集群让其他节点加入(join cluster)
架构图
在普通集群模式中各个节点之间只会互相同步元数据,如果有客户端连接到了节点3想要通过节点3的交换机A找到队列1的内容的话,那么最终还是会请求到节点1上,在这个过程中节点3起到了路由的作用。在普通集群模式中由于不会同步队列中的数据,如果保存队列数据的节点挂了会导致数据丢失,所以我们需要镜像队列模式(基于普通集群模式)。
镜像队列模式
介绍
镜像队列模式下,消息内容会在镜像节点间同步,可用性更高。不过也有一定的副作用,系统性能会降低,节点过多的情况下同步的代价比较大,所以一般是3个节点
架构图
搭建步骤
镜像队列模式是基于普通集群的需要现有普通集群
rabbitmqctl
进入任意一个节点中执行命令:rabbitmqctl set_policy ha-all “^” ‘{“ha-mode”:“all”}’
HTTP API
PUT /api/policies///ha-all {“pattern”:"^ha.", “definition”:{“ha-mode”:“all”}}
Web UI(管控台)
avigate to Admin > Policies > Add / update a policyName 输入:mirror_imagePattern 输入:^(代表匹配所有)Definition 点击 HA mode,右边输入:allAdd policy
Haproxy
介绍
HAProxy是一款提供高可用性,负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费的。
高性能的原因
单进程,事件驱动模型显著降低了上下文切换的开销以及内存占用在任何可用的情况下,单缓冲(single buffering)机制能以不复制任何数据的方式完成读写操作,这会节约大量的CPU时钟周期以及内存带宽借助于Linux上的splice()系统调用,HAProxy可以实现零复制转发,在Linux3.5及以上还可以实现零复制启动内存分配器在固定大小的内存池中可实现即时内存分配,这能够显著减少创建一个会话的时长树形存储:侧重于使用作者多年前开发的弹性二叉树,实现了以O(log(N))的低开销来保持计时器命令,保持运行队列命令及管理轮询及最少连接队列
配置文件
配置文件默认在/usr/local/etc/haproxy下
global
log 127.0.0.1 local0 info
daemon
maxconn 20000
defaults
log global
option tcplog
option dontlognull
retries 5
option redispatch
mode tcp
timeout queue 1m
timeout connect 10s
timeout client 60s
timeout server 15s
timeout check 5s
maxconn 10000
listen stats
mode http
log global
bind 0.0.0.0:8100
stats
enable
stats refresh 30s
stats uri /haproxy
stats hide-version
listen rabbitmq_cluster
bind 0.0.0.0:5672
mode tcp
balance roundrobin
server rabbitmq1 rabbitmq1:5672 check inter 5000 rise 2 fall 2
server rabbitmq2 rabbitmq2:5672 check inter 5000 rise 2 fall 2
server rabbitme3 rabbitmq3:5672 check inter 5000 rise 2 fall 2
docker compose部署RabbitMQ镜像队列(3节点)+Haproxy
目录结构
rabbitmq
docker-compose.yml
config
haproxy.cfg
rabbit1
data1
data2
data3
rabbit2
data1
data2
data3
rabbit3
data1
data2
data3
目录说明
docker-compose.yml——主要文件不做赘述config——Haproxy的配置文件,是Haproxy的数据卷rabbit1,rabbit2,rabbit3——是3个RabbitMQ节点的数据卷(嫌部署麻烦的可以在docker-compose文件去掉这三个目录的数据卷对应)data1对应容器中的/opt/rabbitmq目录data2对应容器中的/var/lib/rabbitmq目录data3对应容器中的/etc/rabbitmq目录
docker-compose.yml
version: '3'
services:
rabbitmq1:
image: rabbitmq
:3.7.17
-management
container_name: rabbitmq1
hostname: rabbitmq1
ports:
- 15673
:15672
- 5673
:5672
environment:
- RABBITMQ_DEFAULT_USER=root
- RABBITMQ_DEFAULT_PASS=123456
- RABBITMQ_ERLANG_COOKIE=SHANGUOYU
- RABBITMQ_NODENAME=rabbitmq1
rabbitmq2:
image: rabbitmq
:3.7.17
-management
container_name: rabbitmq2
hostname: rabbitmq2
ports:
- 15674
:15672
- 5674
:5672
environment:
- RABBITMQ_DEFAULT_USER=root
- RABBITMQ_DEFAULT_PASS=123456
- RABBITMQ_ERLANG_COOKIE=SHANGUOYU
- RABBITMQ_NODENAME=rabbitmq2
rabbitmq3:
image: rabbitmq
:3.7.17
-management
container_name: rabbitmq3
hostname: rabbitmq3
ports:
- 15675
:15672
- 5675
:5672
environment:
- RABBITMQ_DEFAULT_USER=root
- RABBITMQ_DEFAULT_PASS=123456
- RABBITMQ_ERLANG_COOKIE=SHANGUOYU
- RABBITMQ_NODENAME=rabbitmq3
haproxy1:
image: haproxy
:latest
container_name: haproxy1
hostname: haproxy1
volumes:
- ./config
:/usr/local/etc/haproxy
ports:
- 8100
:8100
- 5672
:5672
步骤(rabbit1,rabbit2,rabbit3不是数据卷的部署)
创建rabbitmq目录——mkdir rabbitmq进入rabbitmq目录——cd rabbitmq粘贴docker-compose.yml——推荐在windows上粘贴内容然后使用xftp上传到虚拟机中创建config目录——mkdir config进入config目录——cd config粘贴haproxy.cfg——推荐在windows上粘贴内容然后使用xftp上传到虚拟机中回到rabbitmq目录下——cd …docker-compose up -d启动即可分别进入rabbitmq2和rabbitme3容器中——docker exec -it rabbitmq2或rabbitmq3 /bin/bash分别执行命令
rabbitmqctl stop_apprabbitmqctl resetrabbitmqctl join_cluster --ram rabbitmq1@rabbitmq1rabbitmqctl start_app 随便在一个节点上执行命令形成镜像队列模式——rabbitmqctl set_policy ha-all “^” ‘{“ha-mode”:“all”}’退出容器——exit