RabbitMQ集群搭建

本文遵循BY-SA版权协议,转载请附上原文出处链接。


本文作者: 黑伴白

本文链接: http://heibanbai.com.cn/posts/bae9a0d2/

RabbitMQ 集群

RabbitMQ 是实现了高级消息队列协议(AMQP, Advanced Message Queuing Protocol)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ 服务器是用 Erlang 语言编写的。

RabbitMQ 由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源实现,由以高性能、健壮以及可伸缩性出名的 Erlang 写成。

RabbitMQ大概有 3 种模式:

单一模式:即单机情况不做集群,就单独运行一个 RabbitMQ 而已;

普通模式:默认的普通集群模式,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。

这种方式确实很麻烦,也不怎么好,没做到所谓的分布式,就是个普通集群。因为这导致你要么消费者每次随机连接一个实例然后拉取数据,要么固定连接那个 queue 所在实例消费数据,前者有数据拉取的开销,后者导致单实例性能瓶颈。

而且如果那个放 queue 的实例宕机了,会导致接下来其他实例就无法从那个实例拉取,如果你开启了消息持久化,让 RabbitMQ 落地存储消息的话,消息不一定会丢,得等这个实例恢复了,然后才可以继续从这个 queue 拉取数据。

所以这个事儿就比较尴尬了,这就没有什么所谓的高可用性,这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写操作。

镜像模式 :经典的 Mirror 镜像模式,属于RabbiMQ的HA方案,在对业务可靠性要求较高的场合中比较适用,保证数据不丢失:

  • 高可靠性解决方案,主要就是实现数据的同步,一般来讲是 2 - 3 个节点实现数据同步。
  • 对于 100% 数据可靠性解决方案,一般是采用 3 个节点。
  • 在实际工作中也是用得最多的,并且实现非常的简单,一般互联网大厂都会构建这种镜像集群模式。
  • 要实现镜像模式,需要先搭建一个普通集群模式,在这个模式的基础上再配置镜像模式以实现高可用。

RabbitMQ集群特点

RabbitMQ的集群节点包括内存节点、磁盘节点。RabbitMQ支持消息的持久化 也就是数据写在磁盘上,最合适的方案就是既有内存节点,又有磁盘节点。

环境规划

IP地址 主机名 用途
199.188.166.111 node1 磁盘节点
199.188.166.112 node2 内存节点
199.188.166.113 node3 内存节点

环境依赖

RabbitMQ的依赖包:

  • erlang

  • socat

  • logrotate

erlang安装

rabbitmq是由erlang语言开发的,所以安装rabbitmq之前要先安装erlang,rabbitmq和erlang对应的版本关系可以参考:https://www.rabbitmq.com/which-erlang.html

erlang依赖于ncurses,若缺失请下载安装:Index of /pub/gnu/ncurses

1
2
3
4
5
6
7
8
# 检查系统中是否存在
rpm -qa|grep ncurses

# 安装ncurses
cd ncurses-6.3/
./configure
make
make install

erlang下载地址:Downloads - Erlang/OTP

erlang源码方式安装(可非root用户安装):

1
2
3
4
5
6
tar -zxvf otp_src_24.3.4.3.tar.gz
cd opt_src_4.3.4.3/
mkdir /home/rabbitmq/erlang
./configure --prefix=/home/rabbitmq/erlang
make
make install

确认是否安装成功:

1
2
3
4
5
6
7
8
[rabbitmq@node1 ~]$ cd /home/rabbitmq/erlang/bin
[rabbitmq@node1 bin]$ ./erl
Erlang/OTP 22 [erts-10.5.6] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1]

Eshell V10.5.6 (abort with ^G)
1> halt().
[rabbitmq@node1 bin]$
# halt()是推出系统的方法,注意别忘了后面的点

配置环境变量:

1
2
3
4
5
6
7
8
9
cd ~
vi .bash_profile

# 添加以下内容
# erlang
export PATH=$PATH:/home/rabbitmq/erlang/bin

# 生效环境变量
source ~/.bash_profile

常见错误:

image-20220927093151226

解决方案,只有没有APPLICATIONS DISABLED即可:

1
2
yum install openssl-devel
yum install unixODBC-devel

socat安装

下载地址:socat (dest-unreach.org)

  • 通过源码方式安装
1
2
3
4
5
6
$ wget http://www.dest-unreach.org/socat/download/socat-1.7.3.2.tar.gz
$ tar zxf socat-1.7.3.2.tar.gz
$ cd socat-1.7.3.2
$ ./configure
$ make
$ make install
  • 通过包安装

Centos

1
$ yum install -y socat

Debian/Ubuntu

1
$ apt-get install -y socat

logrotate安装

logrotate 程序是一个日志文件管理工具。用于分割日志文件,删除旧的日志文件,并创建新的日志文件,起到“转储”作用。可以节省磁盘空间。Linux系统默认安装logrotate工具,可自行检查:

1
rpm -qa|grep logrotate

集群安装

RabbitMQ下载

下载地址:Releases · rabbitmq/rabbitmq-server (github.com)

RabbitMQ安装

3台服务器均如此操作

rabbitmq是解压即用的,解压后只需通过在配置文件指定自定义配置即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
xz -d rabbitmq-server-generic-unix-3.10.7.tar.xz
tar xvf rabbitmq-server-generic-unix-3.10.7.tar
cd rabbitmq_server-3.10.7/etc/rabbitmq/

# 新增配置文件rabbitmq-env.conf,指定数据节点名称和路径
# node name
NODENAME=rabbit
# log base
LOG_BASE=/home/rabbitmq/rabbitmq_server-3.10.7/logs
# data dir
MNESIA_BASE=/home/rabbitmq/rabbitmq_server-3.10.7/data
# Specifies new style config file location
CONFIG_FILE=/home/rabbitmq/rabbitmq_server-3.10.7/etc/rabbitmq/rabbitmq.conf
# conf env file
CONF_ENV_FILE=/home/rabbitmq/rabbitmq_server-3.10.7/etc/rabbitmq/rabbitmq-env.conf
# Specifies advanced config file location
ADVANCED_CONFIG_FILE=/home/rabbitmq/rabbitmq_server-3.10.7/etc/rabbitmq/advanced.config

# 新增配置文件rabbitmq.conf指定端口等设置
# listen port
listeners.tcp.default=5672
# log dir 此路径需手动创建
log.dir=/home/rabbitmq/rabbitmq_server-3.10.7/logs
log.file=rabbit.log
# open remote request
loopback_users.guest=false

# 界面管理端口
management.tcp.port = 15672
management.tcp.ip = 0.0.0.0

配置环境变量:

1
2
3
4
5
6
7
8
cd ~
vi .bash_profile
# 添加以下内容
# rabbitmq
export PATH=$PATH:/home/rabbitmq/rabbitmq_server-3.10.7/sbin

# 生效环境变量
source ~/.bash_profile

启动服务

3台服务器均如此操作

1
2
3
4
# 后台启动 可以如此启动,会直接运行在后台 nohup rabbitmq-server -detatched >/dev/null &
rabbitmq-server -detatched
# 直接启动,如果关闭窗口或者需要在改窗口使用其他命令时应用就会停止
rabbitmq-server

如下图所示,启动成功:

image-20220927091115698

查看服务状态

1
rabbitmqctl status

安装管理界面插件

3台服务器均如此操作

1
rabbitmq-plugins enable rabbitmq_management

安装后默认端口位15672,若需修改,可在配置文件中进行配置:

1
2
3
4
# rabbitmq_server-3.10.7/etc/rabbitmq/rabbitmq.conf 增加如下内容:
# 界面管理端口
management.tcp.port = 15672
management.tcp.ip = 0.0.0.0

账号密码默认是:guest/guest,登录如图所示:

image-20220927092532928

用户管理

查看所有用户

1
rabbitmqctl list_users

添加用户

1
2
rabbitmqctl add_user moia 123456
rabbitmqctl add_user shark 123456

设置用户权限

1
rabbitmqctl set_user_tags moia administrator

添加vhost

1
2
rabbitmqctl add_vhost moia
rabbitmqctl add_vhost shark

配置远程访问权限

1
2
3
# -p后第一个参数为vhost 第二个参数为用户名
rabbitmqctl set_permissions -p moia moia "." "." ".*"
rabbitmqctl set_permissions -p shark shark "." "." ".*"

查看用户权限

1
rabbitmqctl list_user_permissions moia

删除用户

1
rabbitmqctl delete_user guest

停止服务

无问题后停止服务,开始进行后续集群的配置:

1
rabbitmqctl stop

HOSTS配置

3台服务器均如此操作

分别修改服务器的/etc/hosts文件,增加ip和主机名映射

1
2
3
4
5
6
vi /etc/hosts

# 增加以下内容
199.188.166.111 node1
199.188.166.112 node2
199.188.166.113 node3

cookie同步

将一台主机上的 .erlang.cookie 文件拷贝到其他两台主机上。该 cookie 文件相当于密钥令牌,集群中的 RabbitMQ 节点需要通过交换密钥令牌以获得相互认证,

因此处于同一集群的所有节点需要具有相同的密钥令牌,否则在搭建过程中会出现 Authentication Fail 错误。

RabbitMQ 服务启动时,erlang VM 会自动创建该 cookie 文件,默认的存储路径为:

1
2
3
$HOME/.erlang.cookie
# 有的可能是此路径
# /var/lib/rabbitmq/.erlang.cookie

默认的.erlang.cookie权限是400,需要先进行权限的更改:

1
2
# 在3台服务器分别操作
chmod 600 /home/rabbitmq/.erlang.cookie

登陆第一台rabbit-1机器node1,拷贝cookie至另外2台机器node2、node3:

1
2
3
# 在node1服务器进行操作
scp /home/rabbitmq/.erlang.cookie rabbitmq@node2:/home/rabbitmq/
scp /home/rabbitmq/.erlang.cookie rabbitmq@node3:/home/rabbitmq/

从节点加入集群

将node2服务器加入集群

1
2
3
4
5
6
7
8
# 启动服务
nohup rabbitmq-server -detatched >/dev/null &
# 停止应用
rabbitmqctl stop_app
# 加入内存节点,若不加--ram参数,则是默认加入磁盘节点
rabbitmqctl join_cluster --ram rabbit@node1
# 启动应用
rabbitmqctl start_app

将node3服务器加入集群

1
2
3
4
5
6
7
8
# 启动服务
nohup rabbitmq-server -detatched >/dev/null &
# 停止应用
rabbitmqctl stop_app
# 加入内存节点,若不加--ram参数,则是默认加入磁盘节点
rabbitmqctl join_cluster --ram rabbit@node1
# 启动应用
rabbitmqctl start_app

注:如果想要更改节点类型,可以使用命令rabbitmqctl change_cluster_node_type disc(ram),前提是必须停掉rabbit应用

1
2
3
4
5
6
7
8
9
10
11
12
13
join_cluster` 命令有一个可选的参数 `--ram` ,该参数代表新加入的节点是内存节点,默认是磁盘节点。

如果是内存节点,则所有的队列、交换器、绑定关系、用户、访问权限和 vhost 的元数据都将存储在内存中,如果是磁盘节点,则存储在磁盘中。

内存节点可以有更高的性能,但其重启后所有配置信息都会丢失,因此RabbitMQ 要求在集群中至少有一个磁盘节点,其他节点可以是内存节点。

当内存节点离开集群时,它可以将变更通知到至少一个磁盘节点;然后在其重启时,再连接到磁盘节点上获取元数据信息。

除非是将 RabbitMQ 用于 RPC 这种需要超低延迟的场景,否则在大多数情况下,RabbitMQ 的性能都是够用的,可以采用默认的磁盘节点的形式。

另外,如果节点以磁盘节点的形式加入,则需要先使用 `reset` 命令进行重置,然后才能加入现有群集,重置节点会删除该节点上存在的所有的历史资源和数据。

采用内存节点的形式加入时可以略过 `reset` 这一步,因为内存上的数据本身就不是持久化的。

命令查看rabbitmq集群的信息

1
rabbitmqctl cluster_status

管理界面查看集群信息

三台服务器组成集群后,登录任意一台的管理界面均能进行查看,可以看到已经是集群状态,node1是disk磁盘节点,node2和node3是ram内存节点:

image-20220928092556193

配置镜像模式

上面已经完成RabbitMQ默认集群模式,但并不保证队列的高可用性,尽管交换机、绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制。

把队列做成镜像队列,让各队列存在于多个节点中,属于RabbitMQ的高可用性方案。镜像模式和普通模式的不同在于,queue和 message 会在集群各节点之间同步,而不是在 consumer 获取数据时临时拉取。

方式一

通过管理界面进行配置

image-20220928094504246

name:自定义,策略名称
Pattern:^ 匹配符,只有一个^代表匹配所有
Definition:ha-mode=all 为匹配类型,分为3种模式:all (mirror to all nodes in the cluster), exactly (mirror to a set number of nodes) or nodes (mirror to an explicit list of nodes). If you choose one of the latter two, you must also set ha-params.

方式二

通过命令行进行配置:

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

蚂蚁🐜再小也是肉🥩!


RabbitMQ集群搭建
http://heibanbai.com.cn/posts/bae9a0d2/
作者
黑伴白
发布于
2022年8月30日
许可协议

“您的支持,我的动力!觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付