延迟队列使用说明

一、应用场景

  1. 对于商城系统而言,定时任务会非常多,比如优惠券过期、订单定时关闭、2小时订单未支付自动取消等等。常用做法是写数据库指定过期时间,定时循环读表,当数据量一大,这种会严重影响性能,产生巨大的io。
  2. 而另外一些基于redis实现的延迟队列,也是基于pull拉模式去实现的,也会产生io,只是变成了内存读取。
  3. 一种好的做法是 push 推模式,服务端主动推送,这里就是rabbitmq的死信队列去实现

二、延迟队列原理

延迟队列一般分为两种:
- 基于消息的延迟和基于队列的延迟。基于消息的延迟是指为每条消息设置不同的延迟时间,那么每当队列中有新消息进入的时候就会重新根据延迟时间排序,当然这也会对性能造成极大的影响。
- 实际应用中大多采用基于队列的延迟,设置不同延迟级别的队列,比如 5s、10s、30s、1min、5mins、10mins 等,每个队列中消息的延迟时间都是相同的,这样免去了延迟排序所要承受的性能之苦,通过一定的扫描策略(比如定时)即可投递超时的消息。
- 这里主要通过rabbitmq的死信队列实现,需要同时声明一个缓冲队列和一个延迟队列,给缓冲队列设置统一消息过期时间,当消息过期后,会自动被重新投递到死信队列(死信队列也是一个普通队列),只需要监听死信队列即可

三、api项目使用说明

  1. 首先需要定义延迟消费队列:即不管是订单关闭,还是优惠券过期的后续处理,都需要去监听这个消息
    在  application/libraries/mq/MqDlxQueue 去定义
    image.png
  2. 运行声明脚本
    php mq/StartDlx.php DELAY_QUEUE_TEST
  3. 定义缓冲区队列:即所有投递到这个队列的消息,设置统一的过期时间,比如固定2小时关闭订单,可以设置统一的队列过期时间为2小时。

    这里需要指定 dlx_key:即过期后投递到的死信队列的路由
    需要指定 message_ttl:即统一的消息过期时间,单位 毫秒

    注意:该 缓冲队列的 key,不要有任何消费者,不然被其他消费者消费后,就不会过期

    在 application/libraries/mq/MqQueue 去定义
    image.png

  4. 声明 缓冲队列
    php mq/Start.php BUFFER_QUEUE_TEST
  5. 设置 延迟队列消费者 
    image.png
  6. 发送 消息到 缓冲区
    image.png
  7. 测试效果:
    image.png

    image.png

RabbitMq 镜像队列集群搭建

建议食用本文前请先阅读【RabbitMq 普通集群搭建】

一、镜像队列集群概念

​ 镜像队列是基于普通集群模式的扩展,普通集群模式下如果某一个节点宕机,该节点下的队列操作将完全失效。而在镜像队列模式下,队列的数据将被复制到所有节点(或者配置过的节点)中,从而保证了一个节点宕机,其余节点也可以正常消费此消息。但此模式下也必然会带来性能下降、内存/磁盘消耗增加、网络IO负担增加等问题,所以镜像队列适用于对高可用要求比较高的系统。

  1. 每个镜像队列由一个主队列和一个或多个镜像组成。每个镜像队列都有自己的主节点,主队列存放于主节点上。对队列产生的操作将首先应用于队列的主节点,然后传播到镜像节点。包括发布队列、向消费者传递消息、跟踪来自消费者的确认等行为。
  2. 发布到集群中的消息将被复制到所有的镜像队列中,消费者连接任意节点消费队列实际上都将被连接至主队列的节点上。如果主队列已经确认消费了消息,则其余镜像队列中的消息将被丢弃。
  3. 如果主队列所在的节点发生异常,默认情况下最“老”的镜像队列将被选举为主队列,当然也可以制定不同的选举策略。

二、配置镜像队列

  1. 将队列配置成镜像队列需要通过创建policy来实现。policy包含策略键ha-mode和其对应的键值ha-params(可选)组成。
  • exactly模式
    • ha-paramscount,表示队列的总数量。
    • count表示主队列+镜像队列的总数量,如果count为1,则表示只存在于主队列。如果 count为2则表示存在主队列和一个镜像队列,以此类推。如果count值大于集群中节点的总数则表示所有节点都将同步一份镜像队列。如果某个镜像队列的节点宕机,则会寻找一个剩余未同步的节点来同步镜像队列。
  • all模式
    • 不需要ha-params
    • 此模式下所有节点都将同步镜像队列,如果有新节点加入,则新节点也会进行同步。官方建议同步镜像队列的节点数为N/2 + 1,其中N表示节点总数。同步到所有节点会增加所有集群节点的负载,包括网络I/O、磁盘I/O和磁盘空间的使用等。
  • nodes模式
    • ha-paramsnode names,节点的名称。
    • 此模式下将在指定的节点上同步镜像队列,如果声明队列时其余节点均不在新,则只会在声明连接的那个节点上创建队列。
  1. 配置policy
  • rabbitmqctl命令配置

    set_policy [-p vhost] [--priority priority] [--apply-to apply-to] name pattern definition

    • name:策略名称
    • pattern:策略匹配符,正则表达式。当与给定资源匹配时,将应用该策略。
    • definition:策略内容定义,JSON字符串。
    • priority:策略的优先级,整数。数字越大,优先级越高。默认值为0。
    • apply-to:策略应用的对象,支持queues,exchanges,all,默认值为all
      // exactly模式,匹配前缀为two的资源
      rabbitmqctl set_policy -p cluster ha-two ^two. '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
      
      // all模式,匹配所有前缀
      rabbitmqctl set_policy -p cluster ha-all ^ '{"ha-mode":"all"}'
      
      // nodes模式,匹配所有前缀
      rabbitmqctl set_policy -p cluster ha-nodes ^ '{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}'
      
  • management管理后台配置

    Admin -> Policies -> Add / update a policy

  1. 新镜像队列同步设置
  • ha-sync-mode:manual

    默认模式,新队列镜像将不同步现有消息,只接收新消息。当消费者消费完所有仅存在于主队列上的消息后,新的队列镜像将随着时间的推移成为和主节点队列相同的精确镜像队列。

  • ha-sync-mode: automatic

    当新队列镜像加入时,队列将自动同步所有消息。

三、额外说明

  1. 独占队列不会被复制为镜像队列。
  2. 主节点队列失效后,其中一个镜像队列将被选举为主队列并带来如下影响:
    1. 与主机点连接的客户端将全部断开。
    2. 运行时间最长的镜像队列将被选举为主队列,如果镜像队列尚未开始同步,则队列上的消息将丢失。
    3. 新的主队列会认为之前所有的消费者的连接都已经断开,它将重新发送旧队列中没有收到ack的消息。这可能出现客户端已经发送过ack, 但是服务端在接收到之前就已宕机的情况,从而导致发送两遍相同的消息,因此所有未确认的消息都将使用redelivered标志重新发送。
    4. 如果消费者连着的是镜像队列节点,并且消费者在启动时设置了x-cancel-on-ha-failover参数,则消费者将收到一个服务端消费取消的通知,如果未设置此参数,则消费者将无法感知主节点已宕机。
    5. 如果使用自动ack机制则消息将丢失。
  3. 如果停止了某个包含主节点队列的节点,则其他节点的镜像队列将被选举为主节点队列。在重新启动此节点后,该节点只会被当做是一个新加入集群的节点,不会重新成为主节点队列。
  4. 在主节点队列宕机并且其他镜像队列尚未同步的极端情况下,rabbitMq集群将拒绝任何镜像队列选举为主队列,整个队将不可用且被关闭。如果在镜像队列尚未同步的情况下也需要将某个镜像队列选举为主队列,需要配置policyha-promote-on-shutdownalways(默认为when-synced),并且ha-promote-on-failure不可配置为hen-synced(默认值为always)。

四、集群测试

  1. 启动节点、创建用户、vhostexchangequeue,启动消费者。(快速启动,参考【RabbitMq 使用docker搭建集群】篇)

    1. 节点:
      1. 节点一:rabbit@clusterRabbit1
      2. 节点二:rabbit@clusterRabbit2
    2. 用户:api_managementadministrator标签,开放虚拟主机cluster所有权限)

    3. 策略:

      rabbitmqctl set_policy -p cluster ha-all ^ '{"ha-mode":"all"}'
      
    4. vhostcluster

    5. exchangecluster(直连交换机)

    6. queue

      1. 节点一 rabbit@clusterRabbit1
        1. 队列一:
        • nameclusterRabbit1Queue1
        • routing_keyclusterRabbit1key
        1. 队列二:
        • nameclusterRabbit1Queue2
        • routing_keyclusterRabbitCommonKey
      2. 节点二 rabbit@clusterRabbit2
        1. 队列三:
        • nameclusterRabbit2Queue1
        • routing_keyclusterRabbit2key
        1. 队列四:
        • nameclusterRabbit2Queue2
        • routing_keyclusterRabbitCommonKey(与队列二 相同)
    7. consumer
      1. 消费者一:
      • 连接节点:节点一 rabbit@clusterRabbit1
      • 消费队列:队列一 clusterRabbit1Queue1
        1. 消费者二:
      • 连接节点:节点一 rabbit@clusterRabbit1
      • 消费队列:队列二 clusterRabbit1Queue2
        1. 消费者三:
      • 连接节点:节点二 rabbit@clusterRabbit2
      • 消费队列:队列三 clusterRabbit2Queue1
        1. 消费者四(非此节点的队列):
      • 连接节点:节点一 rabbit@clusterRabbit1
      • 消费队列:队列三 clusterRabbit2Queue1
        1. 消费者五:
      • 连接节点:节点二 rabbit@clusterRabbit2
      • 消费队列:队列四 clusterRabbit2Queue2
  2. 连接节点二 rabbit@clusterRabbit2,再次声明队列名和队列一同名的队列clusterRabbit1Queue1。【同名队列再次声明】

  • 结果:声明不成功,节点二中没有生成新的clusterRabbit1Queue1队列,而节点一中clusterRabbit1Queue1队列多出了新绑定的routing_key:clusterRabbit2key,这意味着在同一集群中不同节点之间的队列名是唯一的,在一个节点中可以操作另一个节点的队列数据。
  1. 生产者连接节点一 rabbit@clusterRabbit1,发布clusterRabbit1key消息。【发布此节点队列消息】
  • 消费者一 成功接收到消息。
  1. 生产者连接节点二 rabbit@clusterRabbi2,发布clusterRabbit1key消息。【发布非此节点队列消息】
  • 消费者一 成功接收到消息。
  1. 生产者连接节点一 rabbit@clusterRabbit1,发布clusterRabbitCommonKey消息。【多个节点队列绑定相同消息】
  • 消费者二 成功接收到消息。
  • 消费者五 成功接收到消息。
  1. 生产者连接节点一 rabbit@clusterRabbit1,发布clusterRabbit2key消息。【消费非此节点队列消息】
  • 消费三、四 轮询接收到消息。
  1. 关闭节点二 rabbit@clusterRabbit2,连接节点一 rabbit@clusterRabbit1,发布clusterRabbit2key消息【投递消息给集群中意外退出的节点】
  • 连接节点二 rabbit@clusterRabbit2的消费者全部断开,消费者四并未断开。
  • 节点一rabbit@clusterRabbit1 晋升成为队列三、队列四的主节点。
  • 消费者四 可以继续成功接收到消息。
  • 再次启动节点二rabbit@clusterRabbit2,没有再次成为队列三、队列四的主节点,只是复制了队列三、队列四的镜像队列。
  1. 修改消费者四,在ack之前sleep(20),发布clusterRabbit2key消息,并立即关闭节点二 rabbit@clusterRabbit2
  • 和上面一样,消费者四并未断开。
  • 消费者收到两条相同的消息,说明节点二在收到 ack之前宕机后,此消息会被当做未消费的消息重新放入队列后消费。

RabbitMq 使用docker搭建集群

建议食用本文前请先阅读【RabbitMq 普通集群搭建】

一、RabbitMq镜像

  1. 镜像: rabbitmq:3.8-management
  2. 启动参数:
    • --name: 容器名称
    • -h / --hostnamerabbitMq默认节点的 host
    • -v:文件挂载映射
    • -p:端口映射
      • 5672:容器内默认的rabbitMq 启动端口
      • 15672:容器内默认的rabbitMq 管理插件启动端口
  3. 环境变量:(支持所有rabbitMq环境变量)
    • RABBITMQ_NODENAME:节点名称,缺省为 rabbit@[hostname]
    • RABBITMQ_DEFAULT_USER:默认用户名,缺省为guset
    • RABBITMQ_DEFAULT_PASS:默认密码,缺省为 guest
    • RABBITMQ_DEFAULT_VHOST:默认虚拟主机,缺省为/
    • RABBITMQ_ERLANG_COOKIEerlang.cookie

二、搭建集群

  1. 启动多份rabbitMq容器
    # 启动节点一
    docker run -d --hostname clusterRabbit1 --name clusterRabbit1 -p 15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' -v /opt/ci123/www/html/rabbitMq/clusterRabbit1:/var/lib/rabbitmq rabbitmq:3.8-management
    
    # 启动节点二
    docker run -d --hostname clusterRabbit2 --name clusterRabbit2 -p 5673:5672 --link clusterRabbit1:clusterRabbit1 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' -v /opt/ci123/www/html/rabbitMq/clusterRabbit2:/var/lib/rabbitmq rabbitmq:3.8-management
    
  • /var/lib/rabbitmq 是容器内部文件数据存放目录,使用-v进行文件目录挂载。
  • 多个容器之间使用--link <name or id>:alias连接,否则需要自行在各个容器添加供rabbitMq 相互访问的host
  • Erlang Cookie值必须相同,rabbitMQ是通过Erlang实现的,Erlang Cookie相当于不同节点之间相互通讯的秘钥,Erlang节点通过交换Erlang Cookie获得认证。
  1. 启动集群
    1. 设置节点二 rabbit@clusterRabbit2,加入节点一 rabbit@clusterRabbit1的集群
      rabbitmqctl stop_app
      rabbitmqctl reset
      rabbitmqctl join_cluster rabbit@clusterRabbit1
      rabbitmqctl start_app
      
    2. 查看rabbitMq管理后台集群数据

      rabbitmq管理后台

  2. 一键化启动脚本

    #!bin/sh
    # 启动节点一
    docker run -d --hostname clusterRabbit1 --name clusterRabbit1 -p 15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' -v /opt/ci123/www/html/rabbitMq/clusterRabbit1:/var/lib/rabbitmq rabbitmq:3.8-management
    
    # 启动节点二
    docker run -d --hostname clusterRabbit2 --name clusterRabbit2 -p 5673:5672 --link clusterRabbit1:clusterRabbit1 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' -v /opt/ci123/www/html/rabbitMq/clusterRabbit2:/var/lib/rabbitmq rabbitmq:3.8-management
    
    echo "即将开始初始化"
    sleep 5
    # 加入集群
    docker exec -it clusterRabbit2 sh -c 'rabbitmqctl stop_app && rabbitmqctl reset && rabbitmqctl join_cluster rabbit@clusterRabbit1 && rabbitmqctl start_app'
    
    # 添加虚拟主机
    docker exec -it clusterRabbit1 sh -c 'rabbitmqctl add_vhost cluster'
    
    # 添加用户
    docker exec -it clusterRabbit1 sh -c 'rabbitmqctl add_user api_management shijiemori2012'
    
    # 添加用户权限
    docker exec -it clusterRabbit1 sh -c 'rabbitmqctl set_permissions -p cluster api_management ".*" ".*" ".*"'
    
    # 设置用户标签
    docker exec -it clusterRabbit1 sh -c 'rabbitmqctl set_user_tags api_management administrator'
    

RabbitMq 普通集群搭建

一、集群概念

RabbitMQ集群是一个或多个节点的逻辑分组,每个节点共享用户、虚拟主机、队列、交换、绑定路由、运行时参数和其他分布式状态。集群中的节点可以动态地添加/删除,RabbitMQ代理一开始都运行在单个节点上,可以将这些节点连接到集群中,然后再将其转换回各个代理。

  1. 默认情况下,RabbitMq将复制除消息队列外的所有数据至集群中的每一个节点。而消息队列的完整数据只会存放于创建该队列的节点上,其余节点仅保存该队列的元数据和指针(类似于索引)。如果需要复制队列,则需要启用镜像队列集群。

  2. 集群中每个节点是平等的,不存在主从和特殊的节点。

  3. 集群中的节点通过Erlang Cookie相互通信,每个节点必须具有相同的cookie

  4. 节点分为磁盘节点和RAM节点,RAM节点只在RAM中存储内部数据库表,并不存储包括消息、消息存储索引、队列索引和其他节点状态等数据,RAM节点的性能更加高效,但是由于数据是非持久化的,一旦宕机将无法恢复。默认创建的都是磁盘节点。

  5. 单节点拓扑图如下,集群的拓扑是基于多个Node节点的扩展。

    单节点拓扑图

二、配置需求

  1. 配置方式
    • config 文件配置
    • rabbitmqctl命令配置(下文中使用此方法配置)
  2. 集群中的节点名必须是唯一的
    • 可以在启动时使用环境变量RABBITMQ_NODENAME设置
    • 节点名由[节点名称]@[host]组成
  3. 各个节点的启动端口可以被成功连接
  4. 节点之间通过节点名相互访问,要求各个节点之间的host可以相互进行DNS解析
  5. 每个节点之间必须配置相同的Erlang Cookie(多机环境需要额外配置)

三、集群配置

  1. 启动多个独立的节点

    RABBITMQ_NODE_PORT=5674 RABBITMQ_NODE_IPDDRESS=192.168.0.235  RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15673}]" RABBITMQ_NODENAME="clusterRabbit1@VM235"  /usr/local/rabbitmq/3.1.3/sbin/rabbitmq-server -detached
    RABBITMQ_NODE_PORT=5675 RABBITMQ_NODE_IPDDRESS=192.168.0.235  RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15674}]" RABBITMQ_NODENAME="clusterRabbit2@VM235" /usr/local/rabbitmq/3.1.3/sbin/rabbitmq-server -detached
    

    执行完成后,分别创建了名称为clusterRabbit1@VM235,clusterRabbit2@VM235的两个节点。

    VM235需要提前配置host文件,确保各个节点之间的host可以相互进行DNS解析。

  2. 创建集群

    1. 关闭节点clusterRabbit1@VM235
      ./rabbitmqctl -n clusterRabbit1@VM235 stop_app
      
    2. 重置节点clusterRabbit1@VM235
      ./rabbitmqctl -n clusterRabbit1@VM235 reset
      

      必须重置节点才能加入现有集群,重置节点将删除该节点上以前存在的所有资源和数据。这意味着节点不能在成为集群的成员时保留其现有数据,节点中的数据需要进行额外的备份和恢复。

    3. 将节点clusterRabbit1@VM235加入clusterRabbit2@VM235的集群

      ./rabbitmqctl -n clusterRabbit1@VM235 join_cluster clusterRabbit2@VM235
      
    4. 启动节点clusterRabbit1@VM235
      ./rabbitmqctl -n clusterRabbit1@VM235 start_app
      
    5. 查看集群信息
      ./rabbitmqctl -n clusterRabbit1@VM235 cluster_status
      结果:
      Cluster status of node clusterRabbit1@VM235 ...
      [{nodes,[{disc,[clusterRabbit1@VM235,clusterRabbit2@VM235]}]},
      {running_nodes,[clusterRabbit2@VM235,clusterRabbit1@VM235]},
      {partitions,[]}]
      ...done.
      
  3. 集群中节点的关闭与重启
    1. 节点关闭并重启之后会选择一个在线的集群成员(只考虑磁盘节点)进行同步。在重新启动节点时,默认情况下将尝试与该成员联系10次,并有30秒的响应超时。如果该成员在时间间隔内可用则节点将成功启动,并与该成员同步所需内容后继续运行。如果该成员无法响应,则重新启动的节点将放弃同步数据并启动。
    2. 以下情况将导致节点无法重新加入集群:
    • 修改节点名/主机名,节点的数据目录路径会因此更改。
    • 重置节点数据/更换节点数据目录
  4. 移除集群中的节点
    1. 关闭该节点
    2. 重置该节点
    3. 再次启动该节点

四、集群测试

  1. 创建用户、vhostexchangequeue,并启动消费者。【测试基础】
    1. 用户:api_managementmanagement标签,开放虚拟主机cluster所有权限)
    2. vhostcluster
    3. exchangecluster(直连交换机)
    4. queue
      1. 节点一 clusterRabbit1
        1. 队列一:
        • nameclusterRabbit1Queue1
        • routing_keyclusterRabbit1key
        1. 队列二:
        • nameclusterRabbit1Queue2
        • routing_keyclusterRabbitCommonKey
      2. 节点二 clusterRabbit2
        1. 队列三:
        • nameclusterRabbit2Queue1
        • routing_keyclusterRabbit2key
        1. 队列四:
        • nameclusterRabbit2Queue2
        • routing_keyclusterRabbitCommonKey(与队列二 相同)
    5. consumer
      1. 消费者一:
      • 连接节点:节点一 clusterRabbit1
      • 消费队列:队列一 clusterRabbit1Queue1
        1. 消费者二:
      • 连接节点:节点一 clusterRabbit1
      • 消费队列:队列二 clusterRabbit1Queue2
        1. 消费者三(非此节点的队列):
      • 连接节点:节点一 clusterRabbit1
      • 消费队列:队列三 clusterRabbit2Queue1
        1. 消费者四:
      • 连接节点:节点二 clusterRabbit2
      • 消费队列:队列四 clusterRabbit2Queue2
  2. 连接节点二 clusterRabbit2,再次声明队列名和队列一同名的队列clusterRabbit1Queue1。【同名队列再次声明】
    • 结果:声明不成功,节点二中没有生成新的clusterRabbit1Queue1队列,而节点一中clusterRabbit1Queue1队列多出了新绑定的routing_key,这意味着在同一集群中不同节点之间的队列名是唯一的,在一个节点中可以操作另一个节点的队列数据。
  3. 生产者连接节点一 clusterRabbit1,发布clusterRabbit1key消息。【发布此节点队列消息】
    • 消费者一 成功接收到消息
  4. 生产者连接节点二 clusterRabbit2,发布clusterRabbit1key消息。【发布非此节点队列消息】
    • 消费者一 成功接收到消息
  5. 生产者连接节点一 clusterRabbit1,发布clusterRabbitCommonKey消息。【多个节点队列绑定相同消息】
    • 消费者二 成功接收到消息
    • 消费者四 成功接收到消息
  6. 生产者连接节点一 clusterRabbit1,发布clusterRabbit2key消息。【消费非此节点队列消息】
    • 消费三 成功接收到消息
  7. 关闭节点二 clusterRabbit2,连接节点一,发布clusterRabbit2key消息【投递消息给集群中意外退出的节点】
    • 关闭节点二 clusterRabbit2之后,消费者三、四异常退出
    • 投递消息至集群成功
    • 再次启动节点二 clusterRabbit2以及消费者三、四,之前投递的消息没有成功接收

五、使用总结

  1. 同一集群中不同节点之间的队列名是唯一的,在一个节点中可以操作另一个节点的队列数据。
  2. 生产者可以发布集群中任一节点队列绑定的消息,集群将自动匹配出符合条件的节点队列,并投递给消费者进行消费。
  3. 集群中不同节点的队列如果绑定了相同的routing_key,消息将投递到集群中所有符合路由匹配条件的节点队列中。
  4. 消费者可以订阅集群中任意节点的队列。
  5. 集群中某个节点异常退出后,生产者投递到集群中的消息将无法送达至该节点,但是不影响其他节点的接收。(解决这个问题需要使用镜像队列集群)

六、错误记录

  1. 启动新的节点报错:could_not_start,rabbitmq_management

    解决:

    rabbitmq_management插件默认使用的是15672端口,这个端口已被之前启动的节点占用,修改启动命名为 rabbitmq_management插件指定一个新的端口即可。

    RABBITMQ_NODE_PORT=5674 RABBITMQ_NODE_IPDDRESS=192.168.0.235  RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15673}]" RABBITMQ_NODENAME="clusterRabbit1@VM235"  /usr/local/rabbitmq/3.1.3/sbin/rabbitmq-server -detached
    
  2. 【认知错误】rabbitmq_management管理后台Overview中节点的Memory表示使用的内存,Disk space表示剩余可用的磁盘空间,不是已使用的磁盘空间。

  3. 修改节点的host后启动失败:``ERROR: epmd error for host "VM235": nxdomain (non-existing domain)`

    解决:

    VM235需要预先添加到 HOST文件,确保可以被正确解析。

  4. 节点一 clusterRabbit1 退出集群后重新加入集群,再次声明之前的队列提示routing_key绑定不成功

    NOT_FOUND - no binding clusterRabbitCommonKey between exchange 'cluster' in vhost 'cluster' and queue 'clusterRabbit1Queue2' in vhost 'cluster'
    

    此问题是rabbitMq集群本身的问题,且未得到官方明确的解决方案。

    一些临时解放方案: