CentOS 7上RabbitMQ安装实操:Erlang版本匹配与避坑指南
先说我个人的结论在 CentOS 7 上装 RabbitMQ难度从来不在 RabbitMQ 本身而在 Erlang 版本匹配、yum 仓库选择、还有各种启动期的小毛病。很多人跟着旧教程装到一半就卡住不是因为命令敲错而是没搞明白 CentOS 7 这套老环境下消息中间件生态的现状。这篇文章就是一份完整的实操记录从环境准备到验证收尾我把每一步为什么这么做、哪些坑容易踩都写清楚适合刚接触 RabbitMQ 的新手也适合被安装问题折磨过、想一次性捋明白的运维老手。1. 先把版本兼容性搞清楚再动手1.1 为什么在 CentOS 7 上装 RabbitMQ 总比想象中麻烦CentOS 7 是典型的老牌服务器系统默认 yum 源里的软件包普遍偏旧尤其是 Erlang 这类依赖链比较长的运行时环境。RabbitMQ 本身是 Erlang 写的所以它对 Erlang 版本有严格的下限要求。如果你直接yum install erlang装到手的很可能是十几年前的老版本要么版本过低无法启动新版 RabbitMQ要么启动之后出现一堆奇怪的崩溃日志。我之前在一台新机器上就吃过这个亏图省事直接用系统源装了 erlang然后下载最新版 RabbitMQ rpm结果 rabbitmq-server 服务起来不到三秒就挂掉日志里全是undefined function和badmatch之类的报错。后来一查才发现系统源里 erlang 只有 R16 级别最新 RabbitMQ 需要 Erlang 25 以上这俩根本不是一个时代的产物。所以安装前第一件事不是敲命令而是先确定你打算装哪个版本的 RabbitMQ再反推它需要哪个版本的 Erlang。这个顺序一旦反了后期折腾的时间成本会非常高。1.2 RabbitMQ 和 Erlang 的版本对应关系RabbitMQ 官方维护了一份很详细的版本对照表核心逻辑是每个 RabbitMQ 大版本会声明它支持的 Erlang 主版本区间。下面这张表是我整理的常见对应关系帮助你先建立概念RabbitMQ 版本建议 Erlang 版本区间3.8.x21.3 ~ 23.x3.9.x21.3 ~ 24.x3.10.x / 3.11.x23.2 ~ 25.x3.12.x25.x ~ 26.x3.13.x25.x ~ 27.x4.0.x26.2 以上以 CentOS 7 为例我当前实际部署用的是 RabbitMQ 3.12.x 配合 Erlang 25.x这个组合在 CentOS 7 上很常见也是官方明确支持的搭配。选择版本时可以遵循一个原则别追最新的 RabbitMQ 大版本选那种发布了一段时间、补丁版本完善、并且 Erlang 版本区间覆盖你的安装来源的版本。当你确定了版本组合之后接下来就是选择 Erlang 的安装来源。这里就引出了下一节的关键问题在 CentOS 7 上从哪里能拿到指定版本的 Erlang。2. 安装 Erlang这一步决定后面顺利不顺利2.1 用官方 Erlang 仓库安装指定版本在 CentOS 7 上安装 Erlang我推荐优先使用官方 Erlang 仓库而不是系统自带的源。虽然系统源也有 erlang 包但版本完全不可控也不一定跟 RabbitMQ 兼容。具体做法是手动配置一个 yum 仓库文件。在/etc/yum.repos.d/下新建一个erlang.repo写入如下内容[erlang-solutions] nameErlang Solutions baseurlhttps://packages.erlang-solutions.com/rpm/centos/7/x86_64 gpgcheck1 gpgkeyhttps://packages.erlang-solutions.com/rpm/erlang_solutions.asc enabled1这里的baseurl指向的是 CentOS 7 对应架构的 Erlang 软件包目录。配置完成之后先导入 GPG 密钥rpm --import https://packages.erlang-solutions.com/rpm/erlang_solutions.asc然后刷新缓存并查看可用的 Erlang 版本yum clean all yum makecache yum list available erlang --showduplicates如果你看到列出来的版本里有 25.x 或 26.x说明仓库配置成功了。接下来直接安装你需要的版本即可。这里我以 Erlang 25.x 为例yum install -y erlang-25.*安装完之后检查版本确认 Erlang 能正常输出版本号erl -version erl -eval erlang:display(erlang:system_info(otp_release)), halt(). -noshell第二条命令会直接输出 OTP 的发布版本号比如25或26。这个信息比erl -version更准确因为erl -version有时候输出的只是启动器版本。2.2 如果官方仓库不可用可以用零依赖 Erlang 包兜底有些内网环境访问外网受限或者官方仓库在国内网络下速度太慢这时候我比较推荐另一种方案使用 RabbitMQ 官方团队发布的零依赖 Erlang rpm 包。这类包把 Erlang 运行环境整体打包不需要再去解决一堆依赖直接yum localinstall就能装。具体操作是先从提供该 rpm 包的页面下载对应 CentOS 7 的包然后执行yum localinstall -y erlang-25.3.2.16-1.el7.x86_64.rpm这种方式的好处是版本非常明确不容易出现仓库版本漂移的问题。而且它内部已经把运行时所需的依赖都处理好了基本不会报缺依赖。我个人在干净环境里测试过零依赖包和官方 Erlang 仓库安装出来的 Erlang对 RabbitMQ 来说没有本质区别选哪个取决于你的网络环境。如果两种方式都不可行也可以考虑源码编译 Erlang但我不建议在生产环境这么干编译耗时长、依赖复杂后续维护成本也高。2.3 安装完 Erlang 后先确认三件事Erlang 装完之后别急着装 RabbitMQ花三十秒确认三件事第一Erlang 版本能满足 RabbitMQ 的要求。用上面提到的erl -eval命令确认 OTP 版本如果装的是 3.12.x 的 RabbitMQOTP 至少得是 25。第二确认命令路径。安装后erl命令一般在/usr/bin/erl或/usr/local/bin/erl下确保它在 PATH 里。后期如果 RabbitMQ 启动报找不到 Erlang大多是 PATH 问题。第三确认/usr/lib/erlang目录存在且权限正常。有些公司模板机做了安全加固会把/usr/lib下的目录权限改得很严格导致 RabbitMQ 无法读取 Erlang 运行库。这三件事都确认完了才进入真正安装 RabbitMQ 的阶段。3. 安装 RabbitMQ Server 本体3.1 准备官方 yum 仓库RabbitMQ 提供了官方仓库核心配置指向 packagecloud 或 GitHub Releases这两种方式在社区中使用频率最高。我这里以配置 yum 仓库的方式为例新建/etc/yum.repos.d/rabbitmq.repo[rabbitmq-server] namerabbitmq-server baseurlhttps://packagecloud.io/rabbitmq/rabbitmq-server/el/7/$basearch repo_gpgcheck1 gpgcheck1 enabled1 gpgkeyhttps://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey sslverify1 sslcacert/etc/pki/tls/certs/ca-bundle.crt配置好后刷新缓存然后安装yum clean all yum makecache yum install -y rabbitmq-server这种方式的优势是后续升级方便yum update rabbitmq-server就能直接更新。但需要注意如果网络访问 packagecloud 不畅这个仓库配置了也白搭安装时会一直卡在下载环节。3.2 直接下载 rpm 包安装的兜底方案如果你在 pakagecloud 下载很慢我更推荐直接下载 rpm 包本地安装。先到 RabbitMQ 官方发布页面找到对应 CentOS 7 的 rpm 包比如rabbitmq-server-3.12.14-1.el7.noarch.rpm然后执行wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.12.14/rabbitmq-server-3.12.14-1.el7.noarch.rpm yum localinstall -y rabbitmq-server-3.12.14-1.el7.noarch.rpm注意yum localinstall会自动解析 rpm 的依赖如果发现缺什么包它会尝试从已配置的仓库中补齐依赖。在本地安装方式下RabbitMQ 最主要的依赖就是 Erlang而 Erlang 上一步已经装好了所以正常情况下不会有额外的依赖提示。如果本地安装时提示libcrypto.so.10之类的库缺失这不是 RabbitMQ 的问题而是系统基础库版本太旧。CentOS 7 默认装有 openssl 10 系列的库正常情况下不会缺。真遇到这种情况先执行yum install -y openssl补一下基础包再重试。3.3 安装完成后看一眼关键文件不管用哪种方式安装装完之后我会习惯性检查几个关键路径确保文件都放到位了。RabbitMQ 在 CentOS 7 上的主要目录分布如下路径作用/etc/rabbitmq配置文件目录rabbitmq.conf 在这里/usr/lib/rabbitmq主程序目录包含 bin 下的各种脚本/var/lib/rabbitmq数据目录mnesia 数据在这里/var/log/rabbitmq日志目录排错时最常看的地方如果这几个目录都在说明 rpm 包安装得很完整。接下来就可以启动服务了。4. 服务启动、管理插件与初始配置4.1 启动服务并设置开机自启RabbitMQ 安装成功后先用 systemd 启动服务systemctl start rabbitmq-server systemctl enable rabbitmq-server启动之后立刻检查状态systemctl status rabbitmq-server如果状态显示active (running)说明服务正常。但我建议不要只停留在这个层面再执行一次节点健康检查rabbitmq-diagnostics -q ping这条命令如果返回Pong说明 RabbitMQ 节点真的活着Erlang 虚拟机和 RabbitMQ 应用都正常启动。这是排错时最常用的诊断命令比看 systemctl 状态更可靠。4.2 启用 Web 管理插件并放行防火墙端口RabbitMQ 自带一套 Web 管理界面但默认没启用。开启它rabbitmq-plugins enable rabbitmq_management启用成功后RabbitMQ 会监听15672端口这是管理界面的 HTTP 端口。除此之外5672是 AMQP 协议端口应用连接用它25672是节点间通信集群端口。如果你的机器开了防火墙需要放行这几个端口。CentOS 7 默认是 firewalld放行命令如下firewall-cmd --permanent --add-port5672/tcp firewall-cmd --permanent --add-port15672/tcp firewall-cmd --permanent --add-port25672/tcp firewall-cmd --reload如果系统用的是 iptables 而不是 firewalld那就得自己加规则。我遇到过不少云主机镜像把 firewalld 停用、改用 iptables 的情况这种情况下你执行 firewall-cmd 会直接报错需要先确认当前的防火墙管理工具是哪一个。放行之后在浏览器里访问http://服务器IP:15672如果页面能打开说明管理插件正常运行。4.3 创建用户、虚拟主机和权限新装好的 RabbitMQ 默认只有一个guest用户而且这个用户只能从 localhost 访问。线上环境肯定不能直接用这个账号远程连接所以安装后的第一件事就是创建专属用户和虚拟主机。比如创建一个管理员用户rabbitmqctl add_user admin 你的密码 rabbitmqctl set_user_tags admin administratoradministrator标签表示该用户拥有全部管理权限可以登录管理界面、创建用户、管理虚拟主机等。接着创建虚拟主机rabbitmqctl add_vhost myvhost虚拟主机在 RabbitMQ 里相当于一个独立的隔离空间业务应用连接时指定的 vhost 就是这个东西。最后给用户授权rabbitmqctl set_permissions -p myvhost admin .* .* .*这里三个.*分别代表 configure、write、read 三种权限的正则表达式。.*表示对该虚拟主机下的所有资源拥有全部权限。如果你只想让某个用户只能读可以写^$ ^$ .*等更细粒度的规则。4.4 使用 rabbitmqctl 快速验证实例状态配置完成后我用一条命令组合来快速确认实例整体情况rabbitmqctl status重点看输出中的这些信息Erlang version确认和前面装的一致RabbitMQ version确认版本是你想要的Listeners确认 5672 和 15672 端口是否在正常监听Memory、Disk Free排除资源瓶颈问题如果Listeners里 15672 缺失说明管理插件没启成功如果 5672 缺失多半是 Erlang 分布式节点异常。这两个监听端口是判断 RabbitMQ 是否对外可用的最直接证据。5. 安装全程最容易踩的坑和排查思路5.1 远程访问 15672 页面登录提示 guest 用户无法访问这是一个非常经典的问题。你用浏览器访问管理界面输入默认的 guest 用户结果提示Login failed或者user guest can only connect via localhost。原因很简单RabbitMQ 出于安全考虑默认配置了loopback_users [guest]也就是说 guest 账号只允许在服务器本机登录。这个限制从安全角度来说是合理的我强烈不建议通过修改配置来放开 guest 用户。正确的做法就是按 4.3 节创建一个带 administrator 标签的新用户然后用新用户登录。如果你确实有某些内部工具只能用 guest 登录需要自行评估风险后在/etc/rabbitmq/rabbitmq.conf里改成loopback_users none然后重启服务。但这样做等于关闭了默认安全屏障生产环境千万不要这么干。5.2 主机名解析导致节点一直起不来RabbitMQ 启动时会用当前主机名拼出一个节点名默认格式是rabbit主机名。如果服务器的主机名在/etc/hosts里没有对应的本机解析Erlang 节点之间通信就找不到对方导致启动后状态异常或者直接退出。我在本地虚拟机里就遇到过虚拟机的主机名是node01但/etc/hosts里只写了127.0.0.1 localhost没有127.0.0.1 node01。RabbitMQ 启动后日志里反复出现epmd相关错误。排查和解决办法很简单。先查看当前主机名hostname -s然后把主机名加进 hosts 文件echo 127.0.0.1 $(hostname -s) /etc/hosts再重启 RabbitMQsystemctl restart rabbitmq-server这个问题在新装系统上出现频率非常高尤其是那些没有配置规范主机名的机器。装 RabbitMQ 之前把这一步做了后面能省很多事。5.3 端口监听异常5672 没起来RabbitMQ 服务状态显示 active但应用连接 5672 超时这种情况第一步就是看监听端口ss -lntp | grep -E 5672|15672|25672如果 15672 有监听但 5672 没有常见原因是 RabbitMQ 应用没完全启动或者 Erlang 节点配置异常。此时再执行rabbitmqctl stop_app rabbitmqctl start_app强制重启 RabbitMQ 应用。如果还不行就看日志tail -f /var/log/rabbitmq/rabbit主机名.log日志是最忠实的朋友。RabbitMQ 基本会把启动过程中的所有问题都写进这个日志文件很多看起来诡异的问题翻日志都能找到明确线索。5.4 磁盘或内存告警导致生产者被阻塞RabbitMQ 默认在内存使用率达到 40% 或磁盘剩余空间低于 50MB 时会触发水印限制阻塞生产者的消息发布。这在刚安装完、还没调优参数的机器上很容易被忽视。我见过一台内存只有 2G 的小机器跑了个小业务没怎么用就报memory alarm客户端一直收不到响应。查下来发现是默认的内存阈值对于这台小机器来说太高了。解决办法是进入/etc/rabbitmq/rabbitmq.conf调整水印参数vm_memory_high_watermark_relative 0.6 disk_free_limit_relative 1.5前者表示内存水位线提升到总内存的 60%后者表示当磁盘剩余空间小于内存大小的 1.5 倍时触发告警。参数要根据实际业务量和机器配置来定不要照搬。修改后重启 RabbitMQ 生效。5.5 重装或升级后数据残留导致启动异常如果你之前装过旧版 RabbitMQ后来卸载了再重装新版新版本启动时可能读到旧数据目录/var/lib/rabbitmq/mnesia中的残留文件出现各种莫名其妙的冲突比如认证失败、vhost 丢失、甚至节点直接无法启动。遇到这种情况如果确认旧数据没有保留价值可以清空数据目录再重启systemctl stop rabbitmq-server rm -rf /var/lib/rabbitmq/mnesia systemctl start rabbitmq-server清空之后RabbitMQ 会以全新的状态启动默认配置、默认用户都会恢复到初始状态。注意数据目录里还有日志和插件相关文件如果只想清数据不想动日志就只删mnesia目录。6. 装完之后的日常维护与实用建议6.1 给配置文件建立版本管理习惯我强烈建议从安装完成的那一刻起就把/etc/rabbitmq/rabbitmq.conf纳入配置管理。RabbitMQ 的集群配置、用户、权限、策略都可以通过配置文件或脚本管理起来而不是手动敲一堆 rabbitmqctl 命令。我自己常用的做法是把初始化的 rabbitmqctl 命令写成一个 shell 脚本放到/root/rabbitmq-init.sh里。这样换新机器、重装环境时直接执行脚本就能恢复到一致的初始状态不用每次手工敲。脚本大概长这样#!/bin/bash rabbitmqctl add_user admin 密码 rabbitmqctl set_user_tags admin administrator rabbitmqctl add_vhost /production rabbitmqctl set_permissions -p /production admin .* .* .*这个脚本只负责用户和虚拟主机维度更复杂的权限策略建议写到配置文件里管理。6.2 关于端口和客户端连接的一些提醒很多新手以为装完 RabbitMQ只要 5672 端口能通就万事大吉。实际上客户端连接时还有一个很容易忽略的点rabbitmqctl 和客户端代码里填写的 host、port、vhost、username 是否一致。我在排查生产问题时就发现过代码里填的 vhost 名称是/production但管理界面里创建的是production结果客户端连不上还白白查了半天网络。另外如果你在同一台 CentOS 7 上部署了多个 Erlang 应用epmd可能会冲突。RabbitMQ 默认用端口 4369 做 Erlang 节点发现如果其他 Erlang 服务占用了 4369RabbitMQ 的节点通信会失败。排查端口时别忽略 4369。6.3 个人经验装完先跑一个最小验证再交给业务方最后分享一个我自己的习惯每次安装并配置完 RabbitMQ我不会直接把它交给业务方而是先做一轮最小验证。操作很简单就是用官方客户端或者命令行工具在本机发一条消息、收一条消息。在管理界面里直接进入Exchanges和Queues页面创建一个临时队列然后用Publish message功能发一条测试消息再查看队列里的消息数量是否增加随后用Get message拉取这条消息。如果这一进一出都正常说明 AMQP 协议通路、队列存储、消息持久化这几个核心链路都是好的这时候再交给业务方接手心里才有底。安装 RabbitMQ 这件事本身不复杂复杂的是隐藏在版本兼容、初始化配置、网络限制背后的各种细节。把前面这几步按顺序走完排查思路也明确的话CentOS 7 上部署 RabbitMQ 就不会再让你加班了。