rabbitmq集群-普通模式

Posted asa-x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了rabbitmq集群-普通模式相关的知识,希望对你有一定的参考价值。

RabbitMQ的Cluster模式分为两种

  1. 普通模式
  2. 镜像模式

1. 概念解释

1.1 什么是普通模式

普通集群模式,就是将 RabbitMQ 部署到多台服务器上,每个服务器启动一个 RabbitMQ 实例,多个实例之间进行消息通信。

此时我们创建的队列 Queue,它的元数据(主要就是 Queue 的一些配置信息)会在所有的 RabbitMQ 实例中进行同步,但是队列中的消息只会存在于一个 RabbitMQ 实例上,而不会同步到其他队列。

当我们消费消息的时候,如果连接到了另外一个实例,那么那个实例会通过元数据定位到 Queue 所在的位置,然后访问 Queue 所在的实例,拉取数据过来发送给消费者。

这种集群可以提高 RabbitMQ 的消息吞吐能力,但是无法保证高可用,因为一旦一个 RabbitMQ 实例挂了,消息就没法访问了,如果消息队列做了持久化,那么等 RabbitMQ 实例恢复后,就可以继续访问了;如果消息队列没做持久化,那么消息就丢了。

大致的流程图如下图:


*我们会发现,其实队列的数据只是保存了一份,其他的broker只是保留了元数据而已,用来访问交换机,binding或者队列的基本信息(比如地址啥的)

1.2 什么是元数据

元数据包含以下内容:

  • 队列元数据:队列的名称及属性
  • 交换器:交换器的名称及属性
  • 绑定关系元数据:交换器与队列或者交换器与交换器
  • vhost元数据:为vhost内的队列,交换器和绑定提供命名空间及安全属性之间的绑定关系
1.3 节点类型

RabbitMQ 中的节点类型有两种:

  • RAM node:内存节点将所有的队列、交换机、绑定、用户、权限和 vhost 的元数据定义存储在内存中,好处是可以使得交换机和队列声明等操作速度更快。
  • Disk node:将元数据存储在磁盘中,单节点系统只允许磁盘类型的节点,防止重启 RabbitMQ 的时候,丢失系统的配置信息

RabbitMQ 要求在集群中至少有一个磁盘节点,所有其他节点可以是内存节点,当节点加入或者离开集群时,必须要将该变更通知到至少一个磁盘节点。如果集群中唯一的一个磁盘节点崩溃的话,集群仍然可以保持运行,但是无法进行其他操作(增删改查),直到节点恢复。为了确保集群信息的可靠性,或者在不确定使用磁盘节点还是内存节点的时候,建议直接用磁盘节点。

1.4 缺点

我们会发现,在这汇总集群方式中的情形下,我们会遇到如下几个问题

  1. 保存队列的节点很难知道
  2. 一旦保存队列信息的节点宕机,其实,集群还是没办法工作

2 windows下单机配置rabbitmq集群(普通模式)

2.1 安装rabbitmq

参考文章window下单机搭建RabbitMQ多节点集群


分别访问他们的ui管理界面
http://localhost:15673/#/
http://localhost:15674/#/
http://localhost:15675/#/
界面应当如下,节点名称应当会变,但是应当可以访问

2.2 建立集群

关闭rabbitmq node 2,3,让他们加入rabbit1集群

如果是通过rabbitmq-server方式启动的,直接关闭运行界面就可以了,如果是通过rabbitmq-server -detached的话,执行

D:\\tools\\RabbitMQ Server\\rabbitmq_server-3.8.4-2\\sbin>rabbitmqctl stop_app
Stopping rabbit application on node rabbit2@DESKTOP-IB5K0.. ... //成功关闭提示

ok,那我们正式开始,关闭所有的节点(命令基于powershell)

2.2.1 启动rabbit1,执行 .\\rabbitmq-server.bat -detached


打开 http://localhost:15673/#/ 查看信息

2.2.2 将 rabbit2 加入 rabbit1, 在rabbit2的目录下执行:
.\\rabbitmqctl.bat join_cluster rabbit1

出现如下提示,

我们查看http://localhost:15673/#/,

rabbit2节点没有启动,但是加进来了。

2.2.3 启动节点rabbit2

在D:\\rabbitmq_server-3.10.6-2\\sbin 下执行如下命令

rabbitmqctl start_app


rabbit2节点启动了

同理,注册rabbit3到集群中,并且启动
可以在ui中查看到注册进来了

2.2.4 查看集群状态

我们切换到server-1下执行命令

 .\\rabbitmqctl.bat cluster_status

可以查看各种节点的信息

2.2.5 退出集群

假如我们需要结束节点3,那么在对应的目录下,执行命令如下

  1. rabbitmq-server -detached (已经启动可以忽略这一步)
  2. rabbitmqctl stop_app (关闭节点)
  3. rabbitmqctl reset

    我们查看ui管理,发现节点rabbit3确实没了

    至此,普通集群已初步搭建,这种集群可以提高 RabbitMQ 的消息吞吐能力,但是无法保证高可用,因为一旦一个 RabbitMQ 实例挂了,消息就没法访问了,如果消息队列做了持久化,那么等 RabbitMQ 实例恢复后,才可以继续访问;如果消息队列没做持久化,那么消息就丢了。基于这种情况,我们可以将队列设置为镜像队列来解决

3 spring boot + rabbitmq集群(单节点配置)

我们发现无论是访问下面的那个界面,都是出现了集群的信息的
http://localhost:15673/#/
http://localhost:15674/#/
http://localhost:15675/#/

前文请参考:spring-boot rabbitmq整合

3.1 发送单点结合,但是在另外的节点也是可以消费的

如果publish指定集群的某个节点,其他的节点也是可以访问这个message的,除非该节点宕机了。

3.1.1 生产者设置节点是node1-rabbit1

测试
搭建好集群后,我们需要做个测试,我们发送一个mq消息,会发现三个节点都有这个消息,我们修改配置把publish的broker节点设置为5673,而不是address设置集群地址

spring:
  rabbitmq:
    host: 0.0.0.0
    port: 5673
    username: root
    password: root
    publisher-confirms: true    #确认消息已发送到交换机(Exchange)
    publisher-returns: true     #确认消息已发送到队列(Queue)

如果root没有权限,请改成guest/guest都行,我们发送了一个名为TestDirectQueue的队列,我们去

http://localhost:15673/#/queues
http://localhost:15674/#/queues
http://localhost:15675/#/queues

看,我们会发现都有未消费的的message

3.1.2 生产者设置消费者节点是node2-rabbit2

修改consumer配置为:

spring:
  rabbitmq:
    host: 0.0.0.0
    port: 5674
    username: root
    password: root
    virtual-host: pers-xrb
    listener:
      direct:
        retry:
          max-attempts: 3
      simple:
        retry:
          max-attempts: 3
        acknowledge-mode: manual

启动consumer项目,我们可以发现,message被消费完了

总结
我们可以大胆的猜测,保留队列信息的消息在节点1,rabbit1上的,但是集群中的其他节点也是可以消费的。如果节点1的消费者很慢的话,多几个节点也是可以的。但是如果rabbit1节点宕机了,理论上是其他节点应该是消费不了的了。

3.2 基于3.1,停机publish发布的节点-rabbit1,其他节点会丢失该节点信息
3.2.1 停止保存queue信息的节点

如果保存queue 消息队列的节点宕机了的话,那么就会发现,其他节点没有节点信息了,我们发送一个mq后,再执行命令,停止rabbit1

 .\\rabbitmqctl.bat stop_app

在访问 http://localhost:15674/#/ 或者http://localhost:15675/#/ 我们会发现节点 rabbit1停止了,我们再看queue的消息

无法获取对应的消息了,启动消费者会报错

3.2.2 重启停止了的保存queue 消息的节点queue

我们执行命令,重启节点rabbit1

 .\\rabbitmqctl.bat start_app


message又可见了,我们再重启消费者,消费成功

4 spring boot + rabbitmq集群(多节点配置)

参考 3. spring boot + rabbitmq集群(单节点配置) 只需要修改配置文件就可以了。

通常来说,配置rabbitmq的集群应该如下配置,在address中配置多个地址,通过都好分割

spring:
  rabbitmq:
    username: root
    password: root
    publisher-confirms: true    #确认消息已发送到交换机(Exchange)
    publisher-returns: true     #确认消息已发送到队列(Queue)
    addresses: 0.0.0.0:5674,0.0.0.0:5673,0.0.0.0:5675
    listener:
      simple:
        acknowledge-mode: manual

参考
  1. SpringBoot中RabbitMQ集群的搭建详解
  2. window下单机搭建RabbitMQ多节点集群(超详细)

代码地址: https://github.com/GitHubsteven/spring-in-action2.0/tree/master/spring-boot-mesage

以上是关于rabbitmq集群-普通模式的主要内容,如果未能解决你的问题,请参考以下文章

《Linux运维实战:Centos7.6部署rabbitmq3.9.16镜像模式集群》

Centos6.9下RabbitMQ集群部署记录

Centos6.9下RabbitMQ集群部署记录

怎么保证RabbitMQ和kafuka集群的高可用性?

rabbitmq的多种集群模式;镜像集群模式自定义queue同步策略

rabbitmq的多种集群模式;镜像集群模式自定义queue同步策略