linux服务-RabbitMQ 原理与安装

RabbitMQ 原理与安装

参考:RabbitMQ 对 Erlang 版本要求erlang下载页, rabbitmq下载页延时队列插件-rabbitmq-delayed

RabbitMQ 是基于 AMQP(高级消息队列协议) 实现的开源消息中间件,由 Erlang 语言开发,核心优势是高可用、可扩展、支持多种消息模式,广泛用于系统解耦、异步通信、流量削峰等场景。

一、原理

  • 角色与架构

    RabbitMQ 的核心架构包含以下组件,通过 生产者 - 消费者 模型实现消息的可靠传递:

    组件 作用
    生产者(Producer) 发送消息的应用程序,将消息投递到 Exchange。
    消费者(Consumer) 接收消息的应用程序,从 Queue 中获取并处理消息。
    交换机(Exchange) 接收生产者的消息,根据绑定规则(Binding)将消息路由到对应的 Queue。
    队列(Queue) 存储消息的容器,消息最终落地到 Queue,供消费者消费。
    绑定(Binding) 连接 Exchange 和 Queue 的规则,包含路由键(Routing Key)匹配逻辑。
    虚拟主机(VHost) 逻辑隔离的独立环境,可理解为 "命名空间",不同 VHost 互不干扰,支持权限隔离。
    连接(Connection) 生产者 / 消费者与 RabbitMQ 服务器的 TCP 连接(长连接)。
    信道(Channel) 建立在 Connection 之上的轻量级连接,避免频繁创建 TCP 连接,节省资源。
  • 工作流程

    1. 生产者通过 Channel 向 RabbitMQ 服务器发送消息,指定目标 Exchange 和 Routing Key;

    2. Exchange 根据自身类型和 Binding 规则,将消息路由到一个或多个 Queue;

    3. 消费者通过 Channel 监听指定的 Queue,获取并处理消息;

    4. 消息处理完成后,消费者向 RabbitMQ 发送 ACK(确认),RabbitMQ 才会删除该消息(可配置自动 / 手动 ACK)。

  • 交换机(Exchange)类型

    Exchange 是路由消息的核心,不同类型对应不同的路由规则:

    类型 路由规则 典型场景
    Direct 消息的 Routing Key 与 Binding 的 Routing Key 完全匹配,才路由到对应 Queue 一对一消息(精准路由)
    Fanout 忽略 Routing Key,将消息广播到所有绑定的 Queue 广播 / 订阅(如日志推送)
    Topic 支持通配符匹配(* 匹配一个单词,# 匹配多个单词),模糊路由 多对多消息(如按主题分类)
    Headers 不依赖 Routing Key,通过消息头(Headers)键值对匹配 复杂属性匹配(较少用)
  • 核心特性

    • 消息确认机制:生产者确认(Publisher Confirm)确保消息到达 Exchange;消费者 ACK 确保消息被正确处理;
    • 持久化:Queue、Exchange、消息均可配置持久化,避免服务器宕机丢失;
    • 死信队列(DLX):处理失败 / 过期的消息,支持消息重试或归档;
    • 延迟队列:通过死信队列 + TTL(消息过期时间)实现延迟消息;
    • 集群与镜像队列:支持多节点集群,镜像队列保障 Queue 高可用;
    • 限流:消费者可限制单次获取的消息数量,避免过载。

二、单机安装

  • 前置说明

    • RabbitMQ 依赖 Erlang 语言环境,需先安装 Erlang,再安装 RabbitMQ。
    • 服务器已配置网络,关闭 / 放行防火墙(或开放 5672(AMQP)、15672(管理界面)端口);
    • 系统版本:CentOS 7/8、Ubuntu 20.04+ 均可,以下以 CentOS 7 为例。
  • 安装Erlang

    • 通过 YUM 源安装

      bash 复制代码
      # 1. 添加 Erlang 官方 YUM 源
      vim /etc/yum.repos.d/rabbitmq-erlang.repo
      # 写入以下内容(以 Erlang 25.3 为例)
      [rabbitmq-erlang]
      name=rabbitmq-erlang
      baseurl=https://packagecloud.io/rabbitmq/erlang/el/7/$basearch
      repo_gpgcheck=1
      gpgcheck=1
      enabled=1
      gpgkey=https://packagecloud.io/rabbitmq/erlang/gpgkey
             https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
      sslverify=1
      sslcacert=/etc/pki/tls/certs/ca-bundle.crt
      
      # 2. 安装 Erlang
      yum install -y erlang
      
      # 3. 验证 Erlang 安装
      erl -v  # 输出 Erlang 版本即成功
    • 源码安装 <-- 推荐 扩展性更强

      bash 复制代码
      用web界面下载: https://www.erlang.org/patches/otp-26.2.5.16
      
      yum -y install gcc gcc-c++ ncurses-devel wxGTK wxGTK-devel gtk2-devel libGLU-devel openssl openssl-devel
      cd /opt/
      tar xf otp_src_26.2.5.16.tar.gz 
      cd /opt/otp_src_26.2.5.16
        ./configure --prefix=/opt/mq/erlang
        make -j 4 && make -j 4 install
        
      # 验证版本
      /opt/mq/erlang/bin/erl
          Erlang/OTP 26 [erts-14.2.5.12] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
  • 安装 RabbitMQ

    • yum安装

      bash 复制代码
      # 1. 添加 RabbitMQ YUM 源
      vim /etc/yum.repos.d/rabbitmq.repo
      # 写入以下内容(以 RabbitMQ 3.12.x 为例)
      [rabbitmq_server]
      name=rabbitmq_server
      baseurl=https://packagecloud.io/rabbitmq/rabbitmq-server/el/7/$basearch
      repo_gpgcheck=1
      gpgcheck=1
      enabled=1
      gpgkey=https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey
             https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
      sslverify=1
      sslcacert=/etc/pki/tls/certs/ca-bundle.crt
      
      # 2. 安装 RabbitMQ 服务器
      yum install -y rabbitmq-server
      
      # 3. 验证安装
      rabbitmq-server -v  # 输出 RabbitMQ 版本即成功
    • 源码安装

      bash 复制代码
      # 下载包
      wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.13.7/rabbitmq-server-generic-unix-3.13.7.tar.xz
      
      # 解压并配置
      tar xf rabbitmq-server-generic-unix-3.13.7.tar.xz -C /opt/mq/
      cd /opt/mq/
      mv rabbitmq_server-3.13.7/ rabbitmq
      chmod 777 rabbitmq/ -R
      cd rabbitmq
      mkdir license
      mv LICENSE* license    <-- 把源码包里的LICENSE文件都挪走 
      
      # 创建数据/日志目录并授权
      mkdir -p /opt/mq/rabbitmq/{mnesia,log}
      chmod -R 755 /opt/mq/rabbitmq/{mnesia,log}
      • 配置自启脚本

        bash 复制代码
        cat > /etc/systemd/system/rabbitmq-server.service << EOF
        [Unit]
        Description=RabbitMQ Server
        Documentation=man:rabbitmq-server(8)
        After=network.target
        Wants=network.target
        
        [Service]
        User=root
        Group=root
        
        Environment="PATH=/opt/mq/erlang/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        Environment="RABBITMQ_HOME=/opt/mq/rabbitmq"
        Environment="RABBITMQ_MNESIA_BASE=/opt/mq/rabbitmq/mnesia"
        Environment="RABBITMQ_LOG_BASE=/opt/mq/rabbitmq/log"
        ExecStart=/opt/mq/rabbitmq/sbin/rabbitmq-server
        ExecStop=/opt/mq/rabbitmq/sbin/rabbitmqctl stop
        ExecStop=/bin/sh -c 'PID=$(rabbitmqctl status 2>/dev/null | grep "pid" | awk "{print \$2}" | tr -d ","); [ -n "$PID" ] && kill -9 $PID'
        ExecReload=/opt/mq/rabbitmq/sbin/rabbitmqctl stop && /opt/mq/rabbitmq/sbin/rabbitmq-server
        
        Restart=on-failure
        RestartSec=5
        TimeoutStartSec=60
        TimeoutStopSec=60
        LimitNOFILE=65535  # 提高文件描述符限制(生产环境必备)
        LimitNPROC=65535
        PrivateTmp=true
        
        [Install]
        WantedBy=multi-user.target
        
        EOF
      • 启动服务

        bash 复制代码
        # 启动 RabbitMQ
        systemctl start rabbitmq-server
        
        # 设置开机自启
        systemctl enable rabbitmq-server
        
        # 查看状态(active (running) 即为正常)
        systemctl status rabbitmq-server

2.1、启用管理插件

  • RabbitMQ 默认无 Web 界面,需手动启用插件:

    bash 复制代码
    # 配置环境变量
    echo "RABBITMQ_HOME=/opt/mq/erlang" >> /etc/profile
    echo "export PATH=\$RABBITMQ_HOME/bin:\$PATH" >> /etc/profile
    source  /etc/profile
    
    cd /opt/mq/rabbitmq/sbin
    # 启用管理插件
    [root@localhost sbin]# ./rabbitmq-plugins enable rabbitmq_management
    .....
    Applying plugin configuration to rabbit@localhost...
    The following plugins have been enabled:
      rabbitmq_management
      rabbitmq_management_agent
      rabbitmq_web_dispatch
    started 3 plugins.
    
    # 重启服务(可选)
    systemctl restart rabbitmq-server
  • 添加用户

    bash 复制代码
    cd /opt/mq/rabbitmq/sbin
    
    # 1. 添加管理员用户(替换 username/password 为自定义)
    ./rabbitmqctl add_user admin 123456
    
    # 2. 设置用户为管理员角色
    ./rabbitmqctl set_user_tags admin administrator
    
    # 3. 设置用户权限(允许访问所有 VHost,读写所有资源)
    ./rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
    
    # 4. 可选:删除默认 guest 用户(提高安全性)
    ./rabbitmqctl delete_user guest
    
    # 5. 查看用户列表
    ./rabbitmqctl list_users
  • 开放端口(防火墙)- 如开

    bash 复制代码
    # 开放 AMQP 端口(5672)和 Web 管理端口(15672)
    firewall-cmd --add-port=5672/tcp --permanent
    firewall-cmd --add-port=15672/tcp --permanent
    
    # 重启防火墙
    firewall-cmd --reload
  • 访问 Web 管理界面

    打开浏览器,访问 http://服务器IP:15672,输入上述创建的用户名(如 admin)和密码(如 123456),即可进入 RabbitMQ 管理控制台:

    • 可查看 Queue、Exchange、用户、连接等信息;
    • 可手动创建 Queue/Exchange、绑定规则、发送测试消息等。

三、集群安装

RabbitMQ 集群核心是 Erlang 分布式节点通信 + 队列镜像 / 分片 ,实现高可用和负载均衡。以下以 3 节点集群 为例(CentOS 7/8,自定义路径 /opt/mq/rabbitmq/opt/mq/erlang),覆盖集群搭建、镜像队列配置、故障切换全流程。

  • 前置说明

    • 基础环境准备

      节点 IP 主机名(建议) 核心路径
      节点 1(主) 192.168.189.128 rabbitmq-node1 /opt/mq/rabbitmq、/opt/mq/erlang
      节点 2 192.168.189.129 rabbitmq-node2 同上
      节点 3 192.168.189.135 rabbitmq-node3 同上
    • 统一主机名与 hosts 解析

      bash 复制代码
      # 1. 设置主机名(每个节点对应自己的主机名)
      # 节点1:
      hostnamectl set-hostname rabbitmq-node1
      # 节点2:
      hostnamectl set-hostname rabbitmq-node2
      # 节点3:
      hostnamectl set-hostname rabbitmq-node3
      
      # 2. 修改 /etc/hosts,添加所有节点解析
      cat >> /etc/hosts << EOF
      192.168.1.10 rabbitmq-node1
      192.168.1.11 rabbitmq-node2
      192.168.1.12 rabbitmq-node3
      EOF
      
      # 3. 验证解析
      ping rabbitmq-node2 -c 2  # 节点1 ping 节点2,能通即正常
    • 端口说明

      端口号 核心角色 通信对象 开放范围建议 关键作用概括
      4369 Erlang 节点发现 集群内所有节点互访 仅集群内网 节点发现,Erlang 分布式基础
      25672 集群内部通信 集群内所有节点互访 仅集群内网 同步元数据、镜像队列数据复制
      5672 客户端业务通信 生产者 / 消费者 ↔ 集群 仅业务网段 AMQP 协议端口,承载消息收发
      15672 Web 管理界面 运维端 ↔ 集群 仅运维网段 可视化管理、监控集群状态
      • 依赖逻辑: 4369(节点发现)→ 25672(集群通信)→ 5672(业务交互)→ 15672(运维管理)

        • 无 4369:集群节点无法发现彼此,集群搭建失败;
        • 无 25672:节点可发现但无法同步数据,集群退化为独立节点;
        • 无 5672:客户端无法收发消息,业务中断;
        • 无 15672:仅影响可视化管理,不影响集群核心功能。
      • 防火墙配置

        bash 复制代码
        # 临时关闭防火墙(测试环境)
        systemctl stop firewalld && systemctl disable firewalld
        
        # 生产环境开放端口(替代关闭防火墙)
        firewall-cmd --add-port=4369/tcp --permanent
        firewall-cmd --add-port=25672/tcp --permanent
        firewall-cmd --add-port=5672/tcp --permanent
        firewall-cmd --add-port=15672/tcp --permanent
        firewall-cmd --reload
        
        # 富策略
        firewall-cmd --add-rich-rule='rule family="ipv4" source address="地址/32" port port="端口" protocol="tcp" accept' --permanent
        firewall-cmd --reload
    • 统一 Erlang Cookie

      RabbitMQ 集群通过 Erlang Cookie 认证节点,所有节点必须使用相同的 Cookie 文件:

      bash 复制代码
      # 1. 先停止所有节点的 RabbitMQ 服务
      systemctl stop rabbitmq-server
      
      # 2. 从节点1复制 Cookie 到其他节点(推荐以节点1为基准)
      # 节点1 执行(查看 Cookie 路径,默认在 /root/.erlang.cookie):
      cat /root/.erlang.cookie
      
      # 从节点1 scp 到 节点2、3
      scp /root/.erlang.cookie root@rabbitmq-node2:/root/
      scp /root/.erlang.cookie root@rabbitmq-node3:/root/
      
      # 3. 统一 Cookie 权限(所有节点)
      chmod 400 /root/.erlang.cookie  # 必须 400 权限,否则认证失败
  • 从节点1将 erlang、rabbitmq 压缩直接scp到 节点2、3

    • 节点2、3 跟单机一样都配一遍

3.1、初始化集群

  • 启动所有节点的 RabbitMQ 服务

    bash 复制代码
    # 启动服务
    systemctl start rabbitmq-server
    
    # 验证启动状态
    systemctl status rabbitmq-server  # 确保 active (running)
  • 将节点 2、3 加入节点 1 的集群

    bash 复制代码
    # 1. 停止节点 2.3 的 RabbitMQ 应用(保留 Erlang 节点运行)
    /opt/mq/rabbitmq/sbin/rabbitmqctl stop_app
    
    # 2. 重置节点(清空本地数据,避免冲突)
    /opt/mq/rabbitmq/sbin/rabbitmqctl reset
    
    # 3. 加入节点 1 的集群(指定节点 1 的 Erlang 节点名,格式:rabbit@主机名)
    /opt/mq/rabbitmq/sbin/rabbitmqctl join_cluster rabbit@rabbitmq-node1
    
    # 4. 重启 RabbitMQ 应用
    /opt/mq/rabbitmq/sbin/rabbitmqctl start_app
    
    # 5. 验证集群状态
    /opt/mq/rabbitmq/sbin/rabbitmqctl cluster_status
    
    Running Nodes
    
    rabbit@rabbitmq-node1
    rabbit@rabbitmq-node2
    rabbit@rabbitmq-node3

3.2、配置镜像队列

默认集群中,Queue 仅存储在创建它的节点上,若该节点宕机,Queue 不可用。镜像队列 会将 Queue 复制到集群多个节点,实现故障自动切换。

  • 设置镜像队列策略(所有节点生效)

    bash 复制代码
    # 在任意节点执行(推荐节点1)
    /opt/mq/rabbitmq/sbin/rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
    
    # 参数说明:
    # ha-all:策略名称(自定义)
    # "^":匹配所有队列(正则,也可指定特定队列,如 "^order.*" 匹配以 order 开头的队列)
    # ha-mode":"all":将队列镜像到集群所有节点(可选 "exactly" 配置固定数量,如 "ha-params":2 镜像到2个节点)
    # ha-sync-mode":"automatic":自动同步队列数据(默认手动,需手动执行 sync_queue)
    
    # 返回值 Setting policy "ha-all" for pattern "^" to "{"ha-mode":"all","ha-sync-mode":"automatic"}" with priority "0" for vhost "/" ...
  • 验证镜像队列策略

    bash 复制代码
    [root@localhost mq]# /opt/mq/rabbitmq/sbin/rabbitmqctl list_policies
    
    Listing policies for vhost "/" ...
    vhost	name	pattern	apply-to	definition								priority
    /		ha-all	^		all		{"ha-mode":"all","ha-sync-mode":"automatic"}	0

3.3、集群管理与常用操作

  • 查看集群状态

    bash 复制代码
    /opt/mq/rabbitmq/sbin/rabbitmqctl cluster_status
    # 关键输出:
    # - nodes.disc:磁盘节点列表(所有节点默认是磁盘节点)
    # - running_nodes:运行中的节点
    # - partitions:网络分区(空则正常)
    
    Maintenance status
    Node: rabbit@rabbitmq-node1, status: not under maintenance
    关键信息 含义与影响
    状态值:not under maintenance 节点正常对外提供服务,可接收客户端连接(生产者 / 消费者)、参与集群通信(元数据同步、镜像队列复制),无功能限制。
    适用场景 集群日常运行状态,所有节点均在线且正常工作,无需人工干预。
  • 移除集群节点(如移除节点 3)

    bash 复制代码
    # 1. 节点3 执行:停止应用并重置
    /opt/mq/rabbitmq/sbin/rabbitmqctl stop_app
    /opt/mq/rabbitmq/sbin/rabbitmqctl reset
    
    # 2. 节点1 执行:移除节点3
    /opt/mq/rabbitmq/sbin/rabbitmqctl forget_cluster_node rabbit@rabbitmq-node3
    
    # 3. 节点3 执行:重启应用(退出集群后独立运行)
    /opt/mq/rabbitmq/sbin/rabbitmqctl start_app
  • 故障切换测试

    bash 复制代码
    # 1. 停止节点1的 RabbitMQ 服务(模拟宕机)
    systemctl stop rabbitmq-server
    
    # 2. 节点2 查看集群状态(应显示节点1停止,节点2/3运行)
    /opt/mq/rabbitmq/sbin/rabbitmqctl cluster_status
    
    # 3. 验证队列可用性:生产者/消费者连接节点2,仍可正常收发消息
    # 4. 重启节点1(自动重新加入集群)
    systemctl start rabbitmq-server
  • 集群用户同步

    RabbitMQ 集群会自动同步用户、权限、VHost 配置,只需在一个节点创建用户,所有节点生效

    bash 复制代码
    # 在节点1创建管理员用户(所有节点可共用)
    /opt/mq/rabbitmq/sbin/rabbitmqctl add_user admin 123456
    /opt/mq/rabbitmq/sbin/rabbitmqctl set_user_tags admin administrator
    /opt/mq/rabbitmq/sbin/rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"

3.4、启用管理插件

访问任意节点的管理界面(http://节点IP:15672),登录 admin 用户:

  • 顶部导航栏 AdminNodes:查看所有节点状态(运行 / 停止);

  • Queues 页面:队列旁会显示 Mirrored to [2] nodes(镜像到 2 个节点),表示镜像队列生效;

  • AdminPolicies:查看已配置的镜像队列策略。


四、注意事项

  • 注意事项

    • 磁盘节点 vs 内存节点

      • 默认所有节点是 磁盘节点(存储集群元数据、队列数据),生产环境建议至少 2 个磁盘节点(避免单点故障);
      • 内存节点(仅存储内存,速度快):加入集群时指定 --ram,如 rabbitmqctl join_cluster --ram rabbit@rabbitmq-node1,适合高并发读场景。
    • 网络分区处理

      集群节点网络中断会导致 网络分区,需配置自动恢复:

      bash 复制代码
      # 所有节点修改 RabbitMQ 配置文件(/etc/rabbitmq/rabbitmq.conf)
      echo "cluster_partition_handling = autoheal" >> /etc/rabbitmq/rabbitmq.conf
      
      # 重启所有节点
      systemctl restart rabbitmq-server
    • Erlang 版本兼容

      所有节点必须使用 相同版本的 Erlang 和 RabbitMQ,否则集群无法通信。

  • 常见故障排查

    1. 节点加入集群失败

      • 检查 /.erlang.cookie 文件是否一致、权限是否为 400;
      • 检查 hosts 解析是否正确,节点间 4369/25672 端口是否通;
      • 执行 rabbitmqctl status 查看节点状态,确保 Erlang 节点正常运行。
    2. 镜像队列不生效

      • 检查策略是否匹配队列名称(正则是否正确);

      • 新建队列才会应用策略,已有队列需重新创建或手动同步:

        bash 复制代码
        rabbitmqctl sync_queue 队列名
    3. 节点宕机后队列不可用

      • 确认镜像队列策略已配置(ha-mode:all);
      • 检查节点宕机后,其他节点是否在 running_nodes 列表中。
  • 生产环境优化建议

    • 节点数量:建议 3/5 个节点(奇数,避免脑裂);
    • 存储:队列数据目录挂载独立磁盘,开启持久化;
    • 监控:通过 Prometheus + Grafana 监控集群节点状态、队列长度、消息速率;
    • 限流 :配置消费者限流(basic.qos),避免单节点过载;
    • 备份 :定期执行 rabbitmqctl export_definitions 备份集群配置。
相关推荐
骇客野人1 小时前
Java @Mapper 使用注解的方式注入SQL
linux·服务器·windows
hazhanglvfang1 小时前
liunx基础环境排查
linux·运维·服务器
乌萨奇也要立志学C++1 小时前
【Linux】线程控制 POSIX 线程库详解与 C++ 线程库封装实践
linux·c++
huangyuchi.1 小时前
【Linux网络】深入理解守护进程(Daemon)及其实现原理
linux·运维·服务器·c/c++·守护进程·会话·进程组
橙露3 小时前
Nginx Location配置全解析:从基础到实战避坑
java·linux·服务器
starvapour9 小时前
Ubuntu的桌面级程序开机自启动
linux·ubuntu
哇哈哈&10 小时前
gcc9.2的离线安装,支持gcc++19及以上版本
linux·运维·服务器
___波子 Pro Max.11 小时前
Linux快速查看文件末尾字节方法
linux
Caster_Z12 小时前
WinServer安装VM虚拟机运行Linux-(失败,云服务器不支持虚拟化)
linux·运维·服务器