news 2026/11/6 2:49:44

Linux下RabbitMQ安装实战:Erlang版本匹配与离线部署避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux下RabbitMQ安装实战:Erlang版本匹配与离线部署避坑指南

如果你准备在一台干净的 Linux 环境上部署 RabbitMQ,我猜你踩的第一道坎大概率不是 RabbitMQ 本身,而是 Erlang 运行时。RabbitMQ 本身是一个很规矩的消息中间件,安装包也做得比较规范,但它的底层运行时 Erlang/OTP 和 RabbitMQ 之间有严格的版本匹配关系。网上很多教程还在用很老的yum install erlang,装完 RabbitMQ 之后服务直接起不来,这类问题我见过太多次了,最后只能推倒重装,很浪费时间。

这篇文章会把 Linux 下安装 RabbitMQ 的完整流程拆开讲,从 Erlang 怎么下载、怎么选版本,到 RabbitMQ 怎么安装、怎么配置,再到创建账号和常见启动失败排错,全部覆盖。后面我还会专门说一嘴网上分享的 Erlang 网盘地址该怎么用、离线环境怎么拷包,方便你没外网或者官方源下载慢的时候直接绕过去。

如果你是第一次接触 RabbitMQ,或者之前只跑过 Docker 版,这篇文章同样适用。我们这里讲的是原生二进制安装,不依赖容器,也更贴近生产环境的部署习惯。

1. 安装前的整体判断:先把版本匹配放在第一位

RabbitMQ 是用 Erlang/OTP 写的,跑在 BEAM 虚拟机上,所以它和 Erlang 之间的关系不是“装个最新版就行”,而是“版本必须落在官方支持的区间内”。你要是给 RabbitMQ 3.12 配一个 Erlang 22,大概率会出现undefined function、badmatch、模块加载失败这类非常奇怪的问题,看日志根本反应不过来是运行时版本不对。

这里我贴一个大致的对应关系,你装之前务必去官网看最新的兼容矩阵,因为不同小版本还可能继续收窄范围:

RabbitMQ 版本Erlang/OTP 兼容范围(大致)
RabbitMQ 3.10.xErlang 23.2 ~ 25.x
RabbitMQ 3.11.xErlang 23.2 ~ 26.x
RabbitMQ 3.12.xErlang 25.x / 26.x
RabbitMQ 3.13.xErlang 25.x / 26.x / 27.x

我自己的习惯是装 RabbitMQ 之前先在服务器上确认两件事。第一,当前系统 Erlang 版本是多少,可以用erl -version或erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().'来看。第二,目标 RabbitMQ 版本要求什么 Erlang,去官方兼容表里查一下,再决定下载哪个包。这一步能省掉后面一整天的排查时间。

还有一个经常被忽略的点,是机器的主机名。RabbitMQ 启动时节点名默认是rabbit@主机名,它需要靠系统主机名解析出自己的地址。如果/etc/hosts里没有本机主机名对应的解析,后面你会看到epmd error for host这种报错,排查半天也不是端口问题,最后发现是主机名解析,特别气人。

所以在动手之前,我建议你先做三件事:

  • 查看当前系统版本和架构,比如cat /etc/os-release、uname -m。
  • 配置好/etc/hosts,确保本机主机名能解析到内网 IP。
  • 确认防火墙和 SELinux 状态,免得装完一切正常但端口不通。

这些看起来是琐碎的准备工作,但实际部署时占了排错时间的大头。

2. Erlang 安装的三种路径:官方仓库、离线包和网盘备份

Erlang 的安装方式很多,但并不是每一种都适合生产环境。下面按我实际使用频率从低到高排一下。

2.1 直接用系统源安装,正式环境不建议

CentOS 和 Ubuntu 自带的 Erlang 包普遍偏旧。CentOS 7 默认源里那个 Erlang 版本甚至落后到和 RabbitMQ 新版本完全不兼容。即使能装,你还得面对一个繁琐的问题:完整 Erlang 依赖包特别多,yum install erlang会一次性拉进来一堆组件,版本又由系统仓库决定,你根本没法精确控制。

我自己只在纯粹测试某些 Erlang 功能时才会用系统源装,做 RabbitMQ 部署时从不用它。原因很简单:你没法保证系统源里的版本和 RabbitMQ 兼容,装错了还得卸载重来,时间成本太高。

2.2 用 Erlang 官方仓库安装,适合有外网的机器

Erlang Solutions 提供了面向各发行版的 Erlang 仓库,装出来的版本比系统自带的新很多,也更好控制。以红帽系为例,基本过程是先导入 GPG 密钥,再配置 repo 文件,然后直接yum install erlang。

如果网络条件允许,我一般推荐走这条路。它的好处是依赖关系自动解决,装完之后erl命令直接可用,后续升级也方便。但注意仓库地址和配置方式会随官方调整,你要以 erlang.org 或 Erlang Solutions 官网给的最新说明为准,别照着两三年前的教程硬抄。

2.3 离线 RPM 包和网盘备份,内网环境最省心

很多服务器是内网环境,根本没有外网,这时候在线仓库、在线脚本都不好使。最好的办法是找一台有外网的机器,把 Erlang 和 RabbitMQ 的安装包下载好,再拷进内网。

这就说回了标题里提到的网盘地址这件事。我知道很多人找 Erlang 安装包的时候,官方下载页慢得离谱,GitHub 也经常连接超时,所以网盘分享确实是很实际的兜底方案。我在公众号和文章评论区整理过几个常用 Erlang 版本的网盘备份,rpm、deb、tar.gz 三种格式都有,文件名里带了系统版本号避免搞混。

但是说句实在话,网盘分享最大的问题就是链接容易失效。所以我自己的建议是:优先从官方仓库下载,网盘只作为内网拷贝和离线环境下的备选方案。如果你们能在同一套内网环境里找到已经装好的 Erlang,直接打包带走都行,反正 Erlang 基本不依赖什么特殊的系统库。

下载包之后,建议先做一次校验和对比。以 rpm 为例:

sha256sum erlang-25.3.2.6-1.el8.x86_64.rpm

把这个结果和官方发布页上的 SHA256 值对比一下,一致再安装。以前出现过下载源被污染、包被串改的情况,所以这一步虽然麻烦,但保险起见还是值得做。

3. RabbitMQ 安装与基础配置:从 rpm 到管理界面

Erlang 装好之后,RabbitMQ 本身的安装其实相对简单。你需要下载对应系统的 rpm 或 deb 包,先把几个基础依赖装上,再把 RabbitMQ 包装上,最后启动服务和启用管理插件。

3.1 安装方式和前置依赖

我这里以红帽系举例,Ubuntu 的思路类似,把rpm换成dpkg就行。

RabbitMQ 的 rpm 包依赖socat和logrotate,安装前先补上:

sudo yum install -y socat logrotate

然后下载对应你系统的 RabbitMQ 安装包,手动安装:

rpm -ivh rabbitmq-server-3.12.14-1.el8.noarch.rpm

如果系统提示缺少其他依赖,就用yum install -y 缺少的包名补上,再重新执行 rpm 安装。不要重复安装同一个包,也不要在一个系统上混用多个来源的 RabbitMQ 包,容易把配置和脚本弄乱。

装完之后,RabbitMQ 的 systemd 服务会自动注册。接下来先别急着启动,先看一眼/etc/rabbitmq/目录存不存在。这个目录不一定有默认配置文件,但你的自定义配置都要放这里。我一般会手动建一个rabbitmq.conf,而不是依赖默认配置。

3.2 配置文件里的几个关键参数

rabbitmq.conf的语法是 key-value 风格,比较友好。以下是我常用的几个配置:

listeners.tcp.default = 5672 management.tcp.port = 15672 loopback_users.guest = false vm_memory_high_watermark.relative = 0.6 disk_free_limit.absolute = 2GB
  • listeners.tcp.default是 AMQP 协议端口,业务客户端连的就是它。
  • management.tcp.port是管理界面端口。
  • loopback_users.guest这个参数要小心。默认情况下 guest 账号只能通过本机访问,这是安全设计。如果你是在测试环境图省事,可以把它设为 false,生产环境强烈不建议这么干,否则 guest 账号暴露在网络上非常危险。
  • vm_memory_high_watermark.relative表示内存阈值,超过这个比例 RabbitMQ 会进入流控和报警状态。0.6 是一个比较保守的值,内存小的机器可以调低。
  • disk_free_limit.absolute同时低磁限制,避免磁盘写满以后 RabbitMQ 进入“坚持拒绝接受消息”的自我保护状态。

配置改完不用着急,服务启动时会自动加载。我习惯改完配置之后先systemctl restart rabbitmq-server重启一遍,再往下走,避免前一步的配置在运行状态里不生效。

3.3 启用管理插件和防火墙端口

RabbitMQ 的管理界面并不是默认开启的,需要手动启用插件:

rabbitmq-plugins enable rabbitmq_management

执行之后会看到插件列表,里面rabbitmq_management后面出现E(enabled)。如果这台机器之前装过旧版 RabbitMQ,插件启用失败,可以先执行rabbitmq-plugins disable rabbitmq_management再重新启用。

端口方面,至少要放通这几个:

firewall-cmd --permanent --add-port=5672/tcp firewall-cmd --permanent --add-port=15672/tcp firewall-cmd --reload

如果机器开了 SELinux,还要确认它没有拦住 RabbitMQ 监听端口的网络访问。有时候防火墙已经完全放通了,浏览器仍然都打不开管理页面,最后一看是 SELinux 的布尔值没开,这种问题特别容易绕晕人。检查方式:

sestatus getenforce

如果 SELinux 处于 enforcing 模式,又不想直接关闭它,可以用ausearch -m avc -ts recent查看是否有拦截记录,再针对性调整策略。

启动服务时,我推荐用 systemd 方式:

systemctl enable --now rabbitmq-server rabbitmqctl await_startup

await_startup会等待 RabbitMQ 完全启动后再返回,比盲等几秒再硬着头皮查状态靠谱很多。启动完成后用systemctl status rabbitmq-server看一眼,确认进程没有反复重启。

4. 账号、虚拟主机和权限模型这样设才不乱

RabbitMQ 安装完成后,默认会有一个 guest 账号,密码也是 guest,但这个账号默认只能从 localhost 访问。生产环境别指望用它,也没必要给它开放网络访问,直接创建正式账号才是正路。

4.1 创建一个管理员账号

在服务器上执行:

rabbitmqctl add_user admin '你的强密码' rabbitmqctl set_user_tags admin administrator rabbitmqctl set_permissions -p / admin '.*' '.*' '.*'

第一行创建用户,第二行给用户打上administrator标签,第三行授权到默认虚拟主机/。管理员标签在 RabbitMQ 里的权限非常大,包括创建、删除虚拟主机,关闭连接,重置服务等,所以这个账号的密码一定要管好。

命令行里的密码会出现在 shell 历史记录里,这个问题经常被人忽略。如果你对安全要求比较高,可以先执行unset HISTFILE再执行命令,或者把密码通过环境变量传进去,避免密码残留在.bash_history中。

4.2 创建虚拟主机和业务账号

RabbitMQ 里有个“虚拟主机”概念,类似租户隔离。一个项目一个 vhost,消息队列、交换机、绑定关系全部隔离在这个 vhost 里,互不干扰。我习惯用这个方式创建独立环境:

rabbitmqctl add_vhost app_dev rabbitmqctl add_user app_service '业务密码' rabbitmqctl set_permissions -p app_dev app_service '.*' '.*' '.*'

这样的话,业务连接信息就是:AMQP 端口 5672、虚拟主机 app_dev、用户名 app_service、密码写上你自己定的。管理账号和业务账号分开,管理账号负责运维,业务账号只碰自己的 vhost。如果后面排查消息堆积或者连接泄漏,你也可以通过rabbitmqctl list_connections直接看到哪个 vhost 的哪个账号在占用连接。

4.3 权限模型速记

RabbitMQ 的set_permissions后面三个参数分别对应 configure、write、read 三类权限,顺序固定别写反:

  • configure:创建/删除队列和交换机的权限。
  • write:发送消息到交换机、绑定队列的权限。
  • read:消费消息的权限。

所以如果你想要一个只读监控账号,不能写任何数据,就把 configure 和 write 都设成空字符串"",只留 read:

rabbitmqctl set_permissions -p app_dev monitor "" "" ".*"

这样设置之后,这个账号能看消息、能消费,但不能创建队列也不能发消息,适合给监控系统用。

创建账号时如果名称存在,再用add_user会直接报错,你可以用change_password来重置密码:

rabbitmqctl change_password admin '新密码'

所以做脚本的时候要提前判断用户是否存在,不要机械地执行add_user。

5. 给个能直接抄的一键部署脚本和验证方法

如果你需要重复搭建多套环境,一条条命令敲太容易出错。我自己在实际项目里会把安装过程封装成脚本,这里贴一个红帽系可用的版本。思路就是:先装 Erlang,再装 RabbitMQ,然后把插件、服务、账号和虚拟主机全部配置好。

#!/usr/bin/env bash set -euo pipefail ERL_RPM=./erlang-25.3.2.6-1.el8.x86_64.rpm RABBIT_RPM=./rabbitmq-server-3.12.14-1.el8.noarch.rpm # 检查依赖 if ! command -v erl >/dev/null 2>&1; then if [ -f "$ERL_RPM" ]; then rpm -ivh "$ERL_RPM" else echo "未找到 Erlang rpm 包:$ERL_RPM" exit 1 fi fi # RabbitMQ 前置依赖 yum install -y socat logrotate # 安装 RabbitMQ if ! rpm -q rabbitmq-server >/dev/null 2>&1; then rpm -ivh "$RABBIT_RPM" fi # 管理插件 rabbitmq-plugins enable rabbitmq_management # 启动并开机自启 systemctl enable --now rabbitmq-server rabbitmqctl await_startup # 创建管理员账号 if ! rabbitmqctl list_users | grep -q '^admin\s'; then rabbitmqctl add_user admin '你的管理员密码' rabbitmqctl set_user_tags admin administrator rabbitmqctl set_permissions -p / admin '.*' '.*' '.*' fi # 创建业务虚拟主机和账号 if ! rabbitmqctl list_vhosts | grep -q '^app_dev$'; then rabbitmqctl add_vhost app_dev fi if ! rabbitmqctl list_users | grep -q '^app_service\s'; then rabbitmqctl add_user app_service '你的业务密码' rabbitmqctl set_permissions -p app_dev app_service '.*' '.*' '.*' fi rabbitmq-diagnostics -q ping yes | head -n 1 | rabbitmqctl list_users

脚本里的rabbitmq-diagnostics -q ping很关键,它会确认 RabbitMQ 节点是否存活,避免你以为装好了其实服务根本没起来。后面那个list_users是打印当前用户列表,方便你最后肉眼确认。

安装完成之后,验证不能只看 systemd 有没有 active,还要确认端口真的在监听:

ss -tlnp | grep -E '5672|15672'

再通过 HTTP API 检查一次:

curl -s -u admin:'你的管理员密码' http://127.0.0.1:15672/api/overview

返回 JSON 里能看到 cluster 名称和 version,说明管理 API 正常。接着你用浏览器访问http://服务器IP:15672,登录刚才创建的管理员账号,应该就能看到管理界面里队列、交换机、连接这些信息了。

如果脚本执行过程中某一步出错,由于用了set -euo pipefail,脚本会在出错处停下来,方便你顺着报错往上排查。这比自己手动敲命令然后漏掉某个错误要直观得多。

6. 常见问题速查:症状、原因、处理方向

部署 RabbitMQ 时最容易犯的错不是配置复杂,而是版本和系统环境不匹配。下面这张表是我在实际排错里反复用到的方向,看到对应现象可以直接按表里去查:

现象常见原因处理方向
服务启动后马上退出,日志里有undefined function或badmatchErlang 版本与 RabbitMQ 不兼容卸载当前 Erlang,安装兼容版本
启动时报epmd error for host "xxx"主机名无法解析或 /etc/hosts 配置不对检查hostname,把主机名加入/etc/hosts
管理页面打不开,15672 端口没监听管理插件没启用rabbitmq-plugins enable rabbitmq_management
业务端口不通,客户端连不上防火墙或 SELinux 拦截检查 firewalld,查看 SELinux 拦截日志
消费者停止消费,连接一直在但消息堆积内存或磁盘触发流控报警rabbitmqctl status看 alarm 状态,调整阈值
登录管理界面提示 user not found用户创建失败或密码错误rabbitmqctl list_users确认,用change_password重置
同一局域网多节点互相连不上Erlang Cookie 不一致或节点名重复确保所有节点 cookie 相同,主机名唯一

6.1 我印象最深的两个坑

第一个坑是主机名引起的节点名混乱。某次我在内网部署 RabbitMQ,服务端日志里一直报epmd error for host "monitor01",表面看起来像是 4369 端口被占或者 epmd 没起来。我查了好几轮,最后发现问题不在端口,而是/etc/hosts里没有monitor01这个主机名的映射。加上映射之后,重启 RabbitMQ,问题立刻消失。所以遇到 epmd 相关报错,第一反应先查主机名解析,别一上来就重启服务。

第二个坑是 SELinux 拦端口。明明 firewalld 已经放通了 5672 和 15672,从本机访问一切正常,但从其他机器访问就是不通。当时查了半天,后来在 SELinux 的审计日志里看到了拒绝记录,才知道是对应的 SELinux 策略没开放。解决方式有两个,一个是setsebool打开对应端口的权限,另一个是确认 RabbitMQ 的 rpm 包安装时已经自带了 sepolicy 模块,如果自带了,就用semanage port -l | grep 5672去看端口是否被正确标记。这个问题在 Ubuntu 上很少遇到,但在红帽系上特别常见。

6.2 磁盘和内存报警的处理思路

RabbitMQ 有个自我保护机制,当磁盘剩余空间或内存使用率超过阈值时,它不会继续接收新的消息,而是把所有队列标记为流控状态。这个现象在测试环境不明显,因为数据量小,但在生产环境非常容易碰到。

处理有两种思路:

  • 临时清理:把堆积的队列清掉,或者等消费者把消息消费完。
  • 长期调整:调高disk_free_limit.absolute和vm_memory_high_watermark.relative的值。

我自己一般不建议把内存阈值调太高,因为 RabbitMQ 对内存占用比较敏感,一旦被系统换出到 swap,性能会急剧下降。比较稳妥的做法是先扩容机器内存,或者减少单节点上的队列数量,而不是硬调阈值。

7. 关于网盘地址和离线部署,再补充两句

前面说了这么多,回到标题里那个网盘地址。联络方式我在文末已经提到过:评论区或者私信给我你的操作系统版本和需要的 Erlang 版本,我看到后会把网盘目录发给你。如果版本太多,你也可以直接去官方仓库下,但要是网速不理想,网盘备份确实更省事。

补充一个离线部署时非常实用的经验:网盘里不光要放 Erlang 的安装包,最好把 RabbitMQ 的 rpm/deb 包也一起放进去,散部的依赖包也一起整理。比如 socat、logrotate 这些基础依赖,如果内网机器没有外网,离线安装时少一个都装不上。我之前就吃过一次亏,内网机器把 Erlang 和 RabbitMQ 包都拷进去了,却发现 socat 没装,而内网 yum 源也没有这个包的缓存,只能临时去外网找。

所以离线机器的包整理我一般按“部署物料清单”来准备:

  • Erlang 安装包(对应具体 CentOS / Ubuntu 版本)。
  • RabbitMQ 服务安装包。
  • 系统基础依赖 rpm/deb 包,比如 socat、logrotate。
  • 离线安装脚本。

如果你也需要在内网环境复制多套环境,提前把这一套物料整理好,能省很多事。

8. Erlang Cookie 这个隐藏变量,最后提醒两句

RabbitMQ 集群模式下还有一个很容易被忽略的隐藏变量,叫 Erlang Cookie。它本质上是一个文件,里面存着一串密钥,Erlang 节点之间互相信任全靠它。默认位置一般在/var/lib/rabbitmq/.erlang.cookie或执行用户的$HOME/.erlang.cookie。

单机部署的时候你不用特别管它,但一旦你要做多节点集群,所有节点的 Erlang Cookie 必须一致。我把这个文件比作节点间的“握手暗号”,两边对不上,节点之间就会互相拒绝连接,日志里全是 connection refused,但端口又是通的。

我记得一两年第一次搭三节点集群时,为了省事直接把某个节点的.erlang.cookie拷贝到了另外两个节点,结果第二天发现另一个节点上的 RabbitMQ 起不来了,查下来是拷贝过去之后文件的属主变成了 root,而 RabbitMQ 进程用的账户权限不够,读不了这个文件。后来我把 cookie 文件的属主和权限都调整了一下,问题才解决。

如果你也要做集群,我的建议是:

  • 所有节点的 cookie 内容必须一致。
  • cookie 文件权限最好是 400,属主必须是启动 RabbitMQ 的系统用户。
  • 换主机名之后,如果节点连接变奇怪,优先检查 cookie 和 hosts 解析。

Erlang Cookie 这个细节平时看不见摸不着,很多教程也不会特意写,但它就是那种“不出问题不起眼,一出问题找半天”的深层坑。分享出来,希望你不用再走一遍我当年踩过的弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/6 2:49:43

MFC透明图片与动画效果实战:打造生日祝福小程序

简介:这是一份面向编程学习者和图片处理爱好者的生日祝福小程序源码资源,主要解决如何用C与MFC实现带透视化效果和透明叠加的个性化生日图片生成问题。压缩包共27个文件,约22.35MB,以bmp位图素材、cpp源文件、h头文件为主&#xf…

作者头像 李华
网站建设 2026/11/1 23:43:44

操作系统存储管理能力诊断图谱:页表映射与缺页处理实战

1. 这不是一张试卷,而是一把解剖操作系统的手术刀“计算机操作系统 电子科技大学 第三章:存储管理(测试1)”——看到这个标题,很多人第一反应是:又一份高校课后习题?点开就关?别急。…

作者头像 李华
网站建设 2026/11/4 19:44:09

DICOM转NIfTI:医学图像空间语义对齐的6个关键控制点

1. 项目概述:为什么DICOM转NIfTI不是“点几下鼠标”的事,而是医学图像处理的基石动作在某高校医学影像实验室带学生做课题时,我常被问到一个看似简单的问题:“老师,CT原始数据怎么导入ITK-SNAP或者FSL里做分割&#xf…

作者头像 李华
网站建设 2026/11/4 16:30:04

差异基因分析实战:从筛选到表达矩阵构建全流程

从标题“差异基因分析筛选出差异基因表达矩阵”来看,这应该是转录组数据分析里最常被问到、也最能决定后续分析走向的一个环节。我做生信分析这些年,带过的学生、合作过的课题组,几乎每个人都有同一个诉求:拿到测序数据之后&#…

作者头像 李华