前言
本人是一名运维工程师,在此公司接触到 RabbitMQ ,平时针对此软件的工作内容就是集群的安装以及配置监控等,对其的理解也仅仅是知道其是一种消息队列的服务,有队列,队列中有消息,结合大学时的知识知道队列是一种先进先出的数据结构。
有的开发同事告诉我你们运维做到这里就足够了,但是这样就不了解什么是生产者和消费者,以及MQ中具体还有什么概念,每个概念之间的联系是怎样的。
因此我打算从头开始,结合官网的 documentation 以及书籍《RabbitMQ 实战指南》来系统性的学习 RabbitMQ 并做随笔记录。
版本与生命周期
首先我们需要了解 RabbitMQ 的版本,截至目前(2022-12-28),最新的 release 是3.11.5。版本的选择要基于版本的生命周期,如下表所示。
3.9系列,我们在实验环境中就可以抛弃它了。 RabbitMQ的更新迭代还是蛮快的,基本一年1-2个minor版本,我觉得不用强求保持最新(很难保持)。
这里我们需要注意两个版本过期支持时间
- General Support: 指的是来自所有用户反馈的一般性更新。
- Extended Support: 指的是来自用户报告的安全或者比较严重的问题的更新,这些用户报告还得是有付费的商业 license 的报告。
In service for: 指的是这个版本从诞生到 End Of Life(即 End of Extend Support) 一共服役了多久。
关于下个版本何时上线也会在生命周期中阐述,比如 3.12 版本会在2023年的第一季度诞生。
阐述 out of support 的版本。
安装
首先, RabbitMQ 的官网是 https://www.rabbitmq.com/
下载和安装参考:https://www.rabbitmq.com/download.html
这里我的 Linux distribution 是 CentOS ,并且出于实验的目的,我会选择 CentOS Stream 9
MQ的版本就选择 3.11.5
Erlang的版本选择要参考对应的mq的版本的 release 中的要求
This release requires Erlang 25.
也可以参考 RabbitMQ Erlang Version Requirements
我使用虚拟机来安装,我的笔记本(同时也是宿主机 host)的操作系统是 Windows 10 家庭中文版。
我的虚拟机软件是 VirtualBox 7.0.4
这里需要注意的是网络这块,虚拟机的网络是比较复杂的一部分,为了使得 vm, host, vm1 and vm2 之间可以互相通信,目前我们直接使用桥接(Bridge)的方式。
RabbitMQ 的官方 yum 源 Cloudsmith and Packagecloud 都挂了,repository 中的 baseurl 都无法打开了,资源都找不到,这块应该是官方自己的问题,这个问题在2022年10月9日我就发现了,直到2022年12月28日都没有修复。。。
因此我们只好尝试 Generic 安装。Generic 安装适用于
- 安装的过程中无法获取 root 权限的话(比如用户无法执行 sudo 等)。
- 可能需要安装多个版本的 RabbitMQ 在同一台服务器上。
在正式安装MQ前我们需要先安装 Erlang,因为 Erlang 的 yum repository 也挂了,因此我们只能研究 install Erlang from source 了。
Erlang/OTP 源码编译安装
Erlang/OTP 下载和源码编译安装
Erlang 的下载速度非常慢,还会中断,我的PC端有FQ,因此是在PC端事先下载然后使用 rz 上传至虚拟机中。
cd /usr/local/src
wget https://github.com/erlang/otp/releases/download/OTP-25.2/otp_src_25.2.tar.gz
tar -xzf otp_src_25.2.tar.gz
cd otp_src_25.2/
./configure
make && make install
在编译的过程中遇到的报错和解决的方式如下
configure: error: no acceptable C compiler found in $PATH
yum groupinstall "Development Tools"
configure: error: No curses library functions found
yum install ncurses-devel
安装成功后可以使用 erl 测试进入类似交互式的界面,随后使用 q(). 退出。我们只是确保其可以使用即可。
[root@rabbitmq ~]# erl
Erlang/OTP 25 [erts-13.1.3] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit:ns]
Eshell V13.1.3 (abort with ^G)
1> q().
ok
2>
RabbitMQ Generic 安装
Generic 版本的,基本就是下载解压即可使用了。
cd /usr/local/src/
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.11.5/rabbitmq-server-generic-unix-3.11.5.tar.xz
tar -xf rabbitmq-server-generic-unix-3.11.5.tar.xz
mv rabbitmq_server-3.11.5/ /usr/local/
文件和目录结构说明
从上面可以看出我们将其安装在了/usr/local/rabbitmq_server-3.11.5
其中 sbin 目录是程序文件,一般可以加入PATH
环境变量中。包含以下程序文件。
[root@rabbitmq rabbitmq_server-3.11.5]# ls -l sbin/
total 48
-rwxr-xr-x. 1 root root 855 Dec 14 05:28 rabbitmqctl
-rwxr-xr-x. 1 root root 609 Dec 14 05:28 rabbitmq-defaults
-rwxr-xr-x. 1 root root 864 Dec 14 05:28 rabbitmq-diagnostics
-rwxr-xr-x. 1 root root 7164 Dec 14 05:28 rabbitmq-env
-rwxr-xr-x. 1 root root 860 Dec 14 05:28 rabbitmq-plugins
-rwxr-xr-x. 1 root root 859 Dec 14 05:28 rabbitmq-queues
-rwxr-xr-x. 1 root root 5950 Dec 14 05:28 rabbitmq-server
-rwxr-xr-x. 1 root root 857 Dec 14 05:28 rabbitmq-streams
-rwxr-xr-x. 1 root root 858 Dec 14 05:28 rabbitmq-tanzu
-rwxr-xr-x. 1 root root 860 Dec 14 05:28 rabbitmq-upgrade
这些程序文件的具体用法可以参考 Command Line Tools - RabbitMQ
关于目录的结构,可以参考 File and Directory Locations — RabbitMQ ,其中RABBITMQ_BASE
就是我们解压的目录 /usr/local/rabbitmq_server-3.11.5
对照表格
RABBITMQ_CONFIG_FILE
配置文件是空的,只有目录没有文件
[root@rabbitmq rabbitmq_server-3.11.5]# ls -l etc/rabbitmq/
total 0
除了配置文件以外,环境变量也可以用来配置mq。其实环境变量也是写在一个环境变量的配置文件里面。这些默认情况下都是没有的,具体参考 Configuration — RabbitMQ
RABBITMQ_MNESIA_BASE
这个应该是放置mq数据相关的基础目录,也就是说具体的内容是放置在base底下的
[root@rabbitmq rabbitmq_server-3.11.5]# ls -l var/lib/rabbitmq/mnesia/
total 12
drwxr-xr-x. 5 root root 4096 Dec 29 11:08 rabbit@rabbitmq
-rw-r--r--. 1 root root 310 Dec 29 11:05 rabbit@rabbitmq-feature_flags
-rw-r--r--. 1 root root 4 Dec 29 11:08 rabbit@rabbitmq.pid
drwxr-xr-x. 2 root root 6 Dec 29 11:08 rabbit@rabbitmq-plugins-expand
比如 RABBITMQ_MNESIA_DIR
就是在 RABBITMQ_MNESIA_BASE
中以节点名称命名的目录,即 rabbit@rabbitmq
是我们的节点名称。
同时也看到了我们的PID 文件
RABBITMQ_PID_FILE
$RABBITMQ_MNESIA_DIR.pid
/usr/local/rabbitmq_server-3.11.5/var/lib/rabbitmq/mnesia/rabbit@rabbitmq.pid
具体需要时再查阅文档即可,其中有部分文件/目录(比如数据文件部分)需要至少启动一次mq之后才会出现的。
主机名称与节点名称和目录的关系
我们之前说节点名称是rabbit@rabbitmq
,其中@之后的rabbitmq是我的主机名称,这里就需要思考,如果我修改了主机名称,那么mq是否还可以启动?
答案应该是不行的,我的测试方式是启动mq时使用 rabbitmq
作为主机名,然后修改主机名为 rabbitmq-01
,随后尝试停止实例,就会提示我:
Error: unable to perform an operation on node 'rabbit@rabbitmq-01'. Please see diagnostics information and suggestions below.
接下来我将主机名修改回 rabbitmq 随后停止实例。
然后将主机名修改为rabbitmq-01
,启动实例,我们会发现节点名称变为了rabbit@rabbitmq-01
,然后数据目录也多出了新节点名称的目录。
[root@rabbitmq-01 rabbitmq_server-3.11.5]# ls var/lib/rabbitmq/mnesia/
rabbit@rabbitmq rabbit@rabbitmq-01-feature_flags rabbit@rabbitmq-01-plugins-expand rabbit@rabbitmq-plugins-expand
rabbit@rabbitmq-01 rabbit@rabbitmq-01.pid rabbit@rabbitmq-feature_flags
由此可见,主机名称与节点名称是强相关的,不要随意修改!或许,如果有配置文件的话,情况可能会有不同。
后续这台服务器的主机名称就保持为rabbitmq-01
不变。
运行和管理节点
启动命令 sbin/rabbitmq-server
这个是前台启动,当出现 Starting broker... completed with 0 plugins.
就表示启动成功了。但是这样会占用前台界面。
我们也可以使用后台启动的 detached
模式 ,使用命令rabbitmq-server -detached
如果想要停止的话,使用 sbin/rabbitmqctl shutdown
或者 sbin/rabbitmqctl stop
可以使用./sbin/rabbitmqctl status
和./sbin/rabbitmq-diagnostics status
来查看节点运行状态。
端口访问
RabbitMQ 打开TCP端口来监听来自客户端或者CLI的连接。有时候这些连接可能会被 SELinux 之类的拦截。
CLI工具、mq客户端以及mq节点也会打开tcp端口(一般是一些高位数的端口)用于连接服务器。
这些端口大概有以下:
- 4369: epmd, mq节点和cli工具所使用的一种对等发现服务。
- 5672, 5671:
AMQP 0-9-1
和1.0
客户端所使用的不带TLS和带TLS的端口。5672应该是no TLS。这个就是位于mq服务器上被客户端连接的端口。 - 25672: 用于节点之间和CLI工具沟通的端口,端口号默认情况下是 amqp 5672 + 20000。一般情况下,这个端口是不建议开放的,除非用于比如说集群之间使用 federation 或者是 CLI 工具在外部的网络中执行,具体可以参考 Networking and RabbitMQ — RabbitMQ
- 35672-25682: 用于节点之间和CLI工具沟通的端口,具体可以参考 Networking and RabbitMQ — RabbitMQ
- 15672: 这个是当 management 插件启用之后,通过 web 管理 mq 的 http 端口以及使用
rabbitmqadmin
命令。 - 61613, 61614: STOMP 客户端连接的端口,需要STOMP插件的支持。
- 1883, 8883: MQTT客户端连接的端口,需要MQTT插件的支持。
- 15674: STOMP-over-WebSockets clients,需要 Web STOMP 插件的支持。
- 15675: MQTT-over-WebSockets clients,需要 Web MQTT 插件的支持。
- 15692: Prometheus 监控用,需要 Prometheus插件。
默认的用户访问
默认情况下,会存在一个用户名和密码均为guest
的仅允许从本地连接的测试用户。
一般在实际的生产环境中,我们应该将其删除,然后创建其他账户。
rabbitmqctl list_users
rabbitmqctl delete_user "guest"
rabbitmqctl add_user "admin" # 密码 123456
rabbitmqctl set_permissions "admin" ".*" ".*" ".*"
rabbitmqctl set_user_tags admin administrator
但是我们出于学习的实验环境,这个账户不能删除,因为后面关于mq的使用中,官方提供的示例代码需要使用到此用户。
如果没有对应语言的编程基础,是很难去修改代码的。
关于用户和权限,详细可以参考 Authentication, Authorisation, Access Control — RabbitMQ
小结
关于mq的第一篇博文暂时理解到这里即可。
有一些思考:
- 由于我们没有办法通过 yum 安装 RabbitMQ,因此默认情况下我们就没有 systemd service unit 文件了,因此生产环境为了方便管理可能需要自己编写 unit 文件了。
- 上述的关于主机名和节点名称的关系以及配置文件。最好是做到修改 hostname 不会影响 RabbitMQ
后续就准备按照官方的 Getstarted Tutorials 中的7步来继续学习 RabbitMQ