在 FreeBSD 容器上运行 RabbitMQ 集群
作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗
2019/06
我真的很喜欢那种小而简单、专注做好一件事并且做得非常好的专用解决方案——也许是因为我太喜欢 UNIX 了。这种理念的好例子是 Minio 对象存储,它实现了 S3 协议,支持分布式集群、纠删码,并内置了 Web 界面,还有许多其他特性——我曾在《Distributed Object Storage with Minio on FreeBSD》一文中介绍过。
RabbitMQ 是又一个这样的例子——它大概是目前最流行的 AMQP 协议实现之一——同样带有小巧、精致的 Web 界面。但它和 Minio 的区别在于“力量”。Minio 的 Web 界面非常基础、面向用户,大多数管理和配置任务都需要通过 CLI 完成。Minio 的 Web 界面主要提供创建/删除 buckets、上传/下载文件等功能。而 RabbitMQ 的 Web 界面则非常强大,一旦启用,你几乎不再需要命令行了,所有事情都可以通过 Web 界面完成。

和 ActiveMQ、Apache Kafka 等其它消息系统相比,根据 Google Trends 的趋势来看,RabbitMQ 非常流行。

今天我想向你展示在 FreeBSD 容器上构建一个带有镜像队列的高度冗余 RabbitMQ 集群的消息系统。
在 FreeBSD 提供的所有虚拟化方式中(VirtualBox / Bhyve / QEMU / Jail / Docker),我选择了最轻量的 FreeBSD 容器 —— Jail :🙂:
图例依旧保持不变。
在 host 系统上以 root 用户执行的命令:
在 host 系统上以 普通用户 执行的命令:
在 rabbitX Jail 中执行的命令:
Jail 配置
首先我们将创建用于本次部署的基础 Jail。host 系统与这些 Jail 容器 都使用 FreeBSD 11.2-RELEASE 系统。
我们现在已经有了 2 个空的、干净的 Jail。
接下来要把这些 Jail 的配置加入 /etc/jail.conf 文件中。
因为我使用的是笔记本作为 Jail 的宿主机,所以 Jails 将会绑定无线网卡 wlan0,并使用 192.168.43.10X 这些地址。同时我也添加了 10.0.0.10X 这组地址,主要是为了撰写本文时操作更方便。
这就是配置完成后的 /etc/jail.conf 文件的样子。
现在我们可以启动这些 Jail 了。
Jail 已正常运行。
现在是时候给 Jail 添加 DNS 服务器,以便它们能够访问互联网。
现在我们将把软件包源从 'quarterly' 切换到 'latest'。
安装 RabbitMQ 安装
现在我们可以安装包 RabbitMQ 了。
让我们验证包 RabbitMQ 是否安装成功。
配置 RabbitMQ
接下来我们将在 Jail 中配置 /etc/hosts 文件。
……再简单验证。
由于我们已经安装了包 RabbitMQ,现在需要启用并启动它。
如我们所见,需要在每个 Jail 的 /etc/rc.conf 文件中设置 rabbitmq_enable=YES。
现在我们可以在 Jail 中启动 RabbitMQ 了。
现在我们有四个 RabbitMQ 实例已经启动并运行。
默认启用的插件列表:无。
RabbitMQ 插件
现在是时候启用 Web 界面插件了。
现在我们已经在每个 RabbitMQ FreeBSD Jail 中启用了 Web 界面插件。
大写的 ‘E’ 表示这是我们主动启用的插件,而小写的 ‘e’ 表示该插件仅作为其他我们请求启用的插件的依赖而被启用。
现在——为了创建集群——我们需要这些 RabbitMQ 实例共享相同的 ERLANG cookie。在 FreeBSD 系统上,ERLANG cookie 位于 /var/db/rabbitmq/.erlang.cookie。
我们需要先停止 RabbitMQ,以便更改 ERLANG cookie。
接下来在每个 FreeBSD Jail 上设置相同的 ERLANG cookie。
……现在我们需要再次启动它们。
快速验证一下。
RabbitMQ 管理用户
现在我们将在 RabbitMQ 实例中创建管理用户 admin。
我们现在应该可以登录 http://192.168.43.101:15672/(或者 http://10.0.0.101:15672/)的 RabbitMQ 管理页面了。

登录后,将显示给你实用的 RabbitMQ 仪表板。

RabbitMQ 集群设置
接下来我们将创建 RabbitMQ 集群。
首先,我们需要停止 RabbitMQ 的“应用程序”,以便加入集群。
现在我们已经形成了两节点的 RabbitMQ 集群。接下来我们将其重命名为 cluster。
下面是在 Web 界面中查看我们集群的样子。

RabbitMQ 高可用策略
要在 RabbitMQ 中实现 高可用(镜像)队列,需要创建 Policy(策略)。我们将声明 Policy ha,它匹配名称以 ha- 前缀开头的队列,从而将这些队列配置为在集群中的两个节点上镜像。
创建该 Policy 的命令如下:
……或者,你也可以使用 Web 界面来创建该策略。
无论使用哪种方法,最终都会得到所需的 Policy ha,如下所示。

发送消息到队列
现在我们已经有了两节点的 RabbitMQ 集群,并且为名称以 ha- 前缀开头的队列启用了高可用功能。接下来我们将测试 RabbitMQ 设置,使用 send.go 脚本创建并发送消息到队列——正如你可能猜到的,这个脚本是用 Go 语言编写的。我们需要在 host 系统上安装 Go 语言。
安装 Go 语言
这是 send.go 脚本——我们将使用它向 ha-default 队列发送 10 条消息。它基于教程 RabbitMQ Hello World。
接下来我们将运行它。
我们缺少 Go 语言的包 amqp。
需要从页面 https://github.com/streadway/amqp 下载。我们将通过下载整个 ZIP 包的方式获取它。
我们还需要确保 PATH 和 GOPATH 配置正确。为此,需要将它们写入你的交互式 shell 配置文件中。
现在我们可以继续向队列发送消息了。
ha-default 队列已创建并发送了 10 条消息。

现在我们需要从队列中“接收”这些消息,这时 receive.go 脚本就派上用场了。它同样基于教程 RabbitMQ Hello World 。
这是运行后的输出。该程序会一直运行,直到你使用 CTRL-C 快捷键手动结束它。
如果你仔细查看源码,你可能已经注意到,我是在 rabbit1 节点(10.0.0.101)“发送”消息,而在 rabbit2 节点(10.0.0.102)“接收”这些消息的。
简单基准测试
接下来我们将进行简单的基准测试:保持 receive.go 脚本运行,同时修改 send.go 脚本的 for 循环,发送 100000 条消息。
……现在开始发送消息。
这个简单基准测试的结果如下。

在两个 FreeBSD Jails 内,这个 RabbitMQ 集群实例大约可以处理每秒 4000-5000 条消息。
高可用性测试
现在我们将测试 RabbitMQ 集群的高可用性。
目前 ha-default 队列在 rabbit1 节点上。接下来我们将停止 rabbit1 Jail,观察 RabbitMQ Web 界面的反应。
我们的 ha-default 队列在几秒钟内切换到了 rabbit2 节点 —— 高可用功能按预期工作。

接下来启动 rabbit1 Jail,以恢复冗余。

ha-default 队列恢复了冗余,显示 +1 标记,但仍然位于 rabbit2 节点。
……最后一点小庆祝——这是我博客的第 50 篇文章(不包含 Valuable News 系列) :🙂:
更新 1 – 本月 RabbitMQ 动态
文章 RabbitMQ Cluster on FreeBSD Containers 被收录在 This Month in RabbitMQ – July 2019 中。
感谢提及!
更新 2 – 降低 RabbitMQ CPU 使用率
如 Felix Ehlers 在 Twitter 所报告,设置变量 RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+sbwt none" ,可以降低 RabbitMQ 的 CPU 使用率。
最后更新于
这有帮助吗?