集群相关基础知识简述
多个rabbitmq 节点通过网络连接在一起形成一个集群。节点间的通信对客户端是透明的,客户端不论从哪一个节点访问rabbitmq server 都是相同的。
vhost、exchange、user、权限信息 自动复制到集群中的每一个节点。
集群中的队列
独有队列
创建队列的时候设置了此队列只能在某个节点,即从其他节点无法访问独有队列
普通队列(默认)
每个节点都可以访问的队列,但是队列数据其实只在一个节点上,当客户端从其他节点访问此队列时,其他节点会去访问那个真正存放队列的节点,即其他节点只存放普通队列的元数据,而真实数据只存在于一个节点上,这个节点可以说是此队列的主节点。
rabbitmq 集群中,每个节点都是平等的,没有主节点、从节点之分,这也是rabbitmq的设计思想
镜像队列
试想一下,当集群中真实存放队列的节点挂掉,意味着客户端将无法访问此队列,这样集群就无法高可用。所以有了镜像队列:集群中每个节点都有完整的队列数据,每个节点都有一份队列的镜像,这个镜像是实时同步的(有同步,就意味着有了主从),这样当集群中某个节点挂掉,还是可以实现高可用的,所以镜像队列也称为高可用队列。
节点间通信
rabbitmq节点和CLI 工具(如 rabbitmqctl)使用cookie来确定是否允许它们彼此通信。为了使两个节点能够通信,它们必须具有share secret (被称为:Erlang cookie)。cookie通常存储在本地文件。每个集群节点必须具有相同的cookie。如果cookie文件不存在,则在启动rabbitmq服务器时,Erlang VM 将尝试随机生成cookie并创建一个文件。
cookie的生成,应在集群部署阶段完成。
# cookie位置
# 类unix系统
/var/lib/rabbitmq/.erlang.cookie # 由服务器使用
$HOME/.erlang.cookie # 由CLI工具使用
所以在搭建集群时,集群中所有节点的cookie都应该是相同的。
节点数目
因为有些功能(如:仲裁队列、MQTT中的客户端跟踪)需要集群成员即节点之间达成共识,所以集群中的节点数最好使用奇数
节点发现
rabbitmq 集群有很多节点发现方式
1、启动rabbitmq之后,使用命令行工具动态加入节点到集群
2、配置文件发现,在配置文件中直接写死有哪些节点(本次使用)
3、其他:如DNS动态发现等,可以查看官方文档
集群搭建
方案
三个节点 + 镜像队列 + 代理工具(haproxy或keeplived)
# 三个节点分别在三台机器上
192.168.0.1
192.168.0.2
192.168.0.3
# 每台机器都安装了rabbitmq-server,yum install -y rabbitmq-server 并且版本一致,本次测试使用3.7.15
# 每台机器的 /etc/hosts 增加下面的内容
192.168.0.1 rabbit1
192.168.0.2 rabbit2
192.168.0.3 rabbit3
# 设置cookie
# 用一台机器的cookie去覆盖其他两台机器,确保cookie相同
# 增加环境配置文件
cat /etc/rabbitmq/rabbitmq-env.conf
NODENAME=test_rabbit1@rabbit1 # 每台机器不一样,另两台:rabbit2@saaseyerabbit2 rabbit3@saaseyerabbit3
CONFIG_FILE=/etc/rabbitmq/rabbitmq.conf
RABBITMQ_MNESIA_BASE=/data/rabbitmq/mnesia # rabbitmq 目录 rabbitmq用户要有权限
# 增加配置文件
cat /etc/rabbitmq/rabbitmq.conf
log.dir = /log/rabbitmq # rabbitmq 目录 rabbitmq用户要有权限
log.file = rabbitmq.log
log.file.level = info
log.file.rotation.date = $D0
log.file.rotation.count = 5
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config # 配置节点发现方式为配置文件发现(静态),还有其他的发现方式(动态的) 或者直接在命令行加节点
cluster_formation.classic_config.nodes.1 = test_rabbit1@rabbit1
cluster_formation.classic_config.nodes.2 = test_rabbit2@rabbit2
cluster_formation.classic_config.nodes.3 = test_rabbit3@rabbit3
# 创建目录
mkdir -p /log/rabbitmq # 日志目录
mkdir -p /data/rabbitmq # 持久化文件存放目录
chown rabbitmq:rabbitmq /log/rabbitmq
chown rabbitmq:rabbitmq /data/rabbitmq
# 确保三台机器彼此可以互相访问 5672 15672 25672端口 没有被防火墙禁用
# 启动
systemctl start rabbitmq-server
# 这是节点会自动加入集群,可以在任一节点使用如下命令来查看
rabbitmqctl cluster_status
# 如果节点没有加入集群,在节点上执行如下命令
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
# 设置镜像队列,如何设置可以查看官方文档,这个也可以在web管理页面进行设置
rabbitmqctl set_policy test "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}' # 设置一个名字为test 的规则:默认vhost(/)中的所有队列均为镜像队列,且出故障时 自动同步
# 接下来可以在任一节点设置,user、vhost、权限等
# 在每个节点开启 web
rabbitmq-plugins enable rabbitmq_management
此时整个集群已经搭建完成,客户端可以通过任一节点访问rabbitmq,都是相同的效果。
为了实现高可用,客户端可以配置所有的节点,当某个节点无法访问时,去访问其它节点。
当然我们还可以使用代理,来统一入口,代理的组件很多:haproxy、nginx、keepalived(严格来说不是代理),此处我们使用 haproxy
# haproxy 配置
global
maxconn 512
stats socket /tmp/haproxy
defaults
log global
mode http
option abortonclose
compression algo gzip
compression type text/html text/plain application/json
timeout connect 3600s
timeout client 3600s
timeout server 3600s
# haproxy 状态 http://ip:8080/haproxy_status
listen admin_stats
bind *:8080
mode http
log 127.0.0.1 local3 err
stats refresh 60s
stats uri /haproxy_status
stats realm welcome login\ Haproxy
stats auth admin:123456
stats hide-version
stats admin if TRUE
### rabbitmq 集群配置,转发到
listen rabbitmq_cluster
bind *:5672
mode tcp
balance roundrobin
server rabbit1 192.168.0.1:5672 check inter 1000 rise 2 fall 3 weight 1
server rabbit2 192.168.0.2:5672 check inter 1000 rise 2 fall 3 weight 1
server rabbit3 192.168.0.3:5672 check inter 1000 rise 2 fall 3 weight 1
listen rabbitmq_manage
bind *:15672
mode tcp
balance roundrobin
server rabbit1 192.168.0.1:15672 check inter 1000 rise 2 fall 3 weight 1
server rabbit2 192.168.0.2:15672 check inter 1000 rise 2 fall 3 weight 1
server rabbit3 192.168.0.3:15672 check inter 1000 rise 2 fall 3 weight 1
使用如上配置启动haproxy即可,之后客户端可以直接访问haproxy