文章目录

  • 1. 两种模式
    • 1.1 普通集群
    • 1.2 镜像集群
    • 1.3 节点类型
  • 2. 搭建普通集群
    • 2.1 预备知识
    • 2.2 开始搭建
    • 2.3 代码测试
    • 2.4 反向测试
  • 3. 搭建镜像集群
    • 3.1 网页配置镜像队列
    • 3.2 命令行配置镜像队列
  • 4. 小结

单个的 RabbitMQ 肯定无法实现高可用,要想高可用,还得上集群。

今天松哥就来和大家聊一聊 RabbitMQ 集群的搭建。

1. 两种模式

说到集群,小伙伴们可能第一个问题是,如果我有一个 RabbitMQ 集群,那么是不是我的消息集群中的每一个实例都保存一份呢?

这其实就涉及到 RabbitMQ 集群的两种模式:

  • 普通集群
  • 镜像集群

1.1 普通集群

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

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

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

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

大致的流程图如下图:

1.2 镜像集群

它和普通集群最大的区别在于 Queue 数据和原数据不再是单独存储在一台机器上,而是同时存储在多台机器上。也就是说每个 RabbitMQ 实例都有一份镜像数据(副本数据)。每次写入消息的时候都会自动把数据同步到多台实例上去,这样一旦其中一台机器发生故障,其他机器还有一份副本数据可以继续提供服务,也就实现了高可用。

大致流程图如下图:

1.3 节点类型

RabbitMQ 中的节点类型有两种:

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

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

2. 搭建普通集群

2.1 预备知识

大致的结构了解了,接下来我们就把集群给搭建起来。先从普通集群开始,我们就使用 docker 来搭建。

搭建之前,有两个预备知识需要大家了解:

  1. 搭建集群时,节点中的 Erlang Cookie 值要一致,默认情况下,文件在 /var/lib/rabbitmq/.erlang.cookie,我们在用 docker 创建 RabbitMQ 容器时,可以为之设置相应的 Cookie 值。
  2. RabbitMQ 是通过主机名来连接服务,必须保证各个主机名之间可以 ping 通。可以通过编辑 /etc/hosts 来手工添加主机名和 IP 对应关系。如果主机名 ping 不通,RabbitMQ 服务启动会失败(如果我们是在不同的服务器上搭建 RabbitMQ 集群,大家需要注意这一点,接下来的 2.2 小结,我们将通过 Docker 的容器连接 link 来实现容器之间的访问,略有不同)。

2.2 开始搭建

执行如下命令创建三个 RabbitMQ 容器:

docker run -d --hostname rabbit01 --name mq01 -p 5671:5672 -p 15671:15672 -e RABBITMQ_ERLANG_COOKIE="javaboy_rabbitmq_cookie" rabbitmq:3-management
docker run -d --hostname rabbit02 --name mq02 --link mq01:mylink01 -p 5672:5672 -p 15672:15672 -e RABBITMQ_ERLANG_COOKIE="javaboy_rabbitmq_cookie" rabbitmq:3-management
docker run -d --hostname rabbit03 --name mq03 --link mq01:mylink02 --link mq02:mylink03 -p 5673:5672 -p 15673:15672 -e RABBITMQ_ERLANG_COOKIE="javaboy_rabbitmq_cookie" rabbitmq:3-management

运行结果如下:

三个节点现在就启动好了,注意在 mq02 和 mq03 中,分别使用了 --link 参数来实现容器连接,关于这个参数,如果大家不懂,可以在公众号江南一点雨后台回复 docker,由松哥写的 docker 入门教程,里边有讲这个。这里我就不啰嗦了。另外还需要注意,mq03 容器中要既能够连接 mq01 也能够连接 mq02。

接下来进入到 mq02 容器中,首先查看一下 hosts 文件,可以看到我们配置的容器连接已经生效了:

将来在 mq02 容器中,就可以通过 mylink01 或者 rabbit01 访问到 mq01 容器了。

接下来我们开始集群的配置。

分别执行如下命令将 mq02 容器加入集群中:

rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit01
rabbitmqctl start_app

接下来输入如下命令我们可以查看集群的状态:

rabbitmqctl cluster_status

可以看到,集群中已经有两个节点了。

接下来通过相同的方式将 mq03 也加入到集群中:

rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit01
rabbitmqctl start_app

接下来,我们可以查看集群信息:

可以看到,此时集群中已经有三个节点了。

其实,这个时候,我们也可以通过网页来查看集群信息,在三个 RabbitMQ 实例的 Web 端首页,都可以看到如下内容:

2.3 代码测试

接下来我们来简单测试一下这个集群。

我们创建一个名为 mq_cluster_demo 的父工程,然后在其中创建两个子工程。

第一个子工程名为 provider,是一个消息生产者,创建时引入 Web 和 RabbitMQ 依赖,如下:

然后配置 applicaiton.properties,内容如下(注意集群配置):

spring.rabbitmq.addresses=localhost:5671,localhost:5672,localhost:5673
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

接下来提供一个简单的队列,如下:

@Configuration
public class RabbitConfig {public static final String MY_QUEUE_NAME = "my_queue_name";public static final String MY_EXCHANGE_NAME = "my_exchange_name";public static final String MY_ROUTING_KEY = "my_queue_name";@BeanQueue queue() {return new Queue(MY_QUEUE_NAME, true, false, false);}@BeanDirectExchange directExchange() {return new DirectExchange(MY_EXCHANGE_NAME, true, false);}@BeanBinding binding() {return BindingBuilder.bind(queue()).to(directExchange()).with(MY_ROUTING_KEY);}
}

这个没啥好说的,都是基本内容,接下来我们在单元测试中进行消息发送测试:

@SpringBootTest
class ProviderApplicationTests {@AutowiredRabbitTemplate rabbitTemplate;@Testvoid contextLoads() {rabbitTemplate.convertAndSend(null, RabbitConfig.MY_QUEUE_NAME, "hello 江南一点雨");}}

这条消息发送成功之后,在 RabbitMQ 的 Web 管理端,我们会看到三个 RabbitMQ 实例上都会显示有一条消息,但是实际上消息本身只存在于一个 RabbitMQ 实例。

接下来我们再创建一个消息消费者,消息消费者的依赖以及配置和消息生产者都是一模一样,我就不重复了,消息消费者中增加一个消息接收器:

@Component
public class MsgReceiver {@RabbitListener(queues = RabbitConfig.MY_QUEUE_NAME)public void handleMsg(String msg) {System.out.println("msg = " + msg);}
}

当消息消费者启动成功后,这个方法中只收到一条消息,进一步验证了我们搭建的 RabbitMQ 集群是没问题的。

2.4 反向测试

接下来松哥再举两个反例,以证明消息并没有同步到其他 RabbitMQ 实例。

确保三个 RabbitMQ 实例都是启动状态,关闭掉 Consumer,然后通过 provider 发送一条消息,发送成功之后,关闭 mq01 实例,然后启动 Consumer 实例,此时 Consumer 实例并不会消费消息,反而会报错说 mq01 实例连接不上,这个例子就可以说明消息在 mq01 上,并没有同步到另外两个 MQ 上。相反,如果 provider 发送消息成功之后,我们没有关闭 mq01 实例而是关闭了 mq02 实例,那么你就会发现消息的消费不受影响。

3. 搭建镜像集群

所谓的镜像集群模式并不需要额外搭建,只需要我们将队列配置为镜像队列即可。

这个配置可以通过网页配置,也可以通过命令行配置,我们分别来看。

3.1 网页配置镜像队列

先来看看网页上如何配置镜像队列。

点击 Admin 选项卡,然后点击右边的 Policies,再点击 Add/update a policy,如下图:

接下来添加一个策略,如下图:

各参数含义如下:

  • Name: policy 的名称。
  • Pattern: queue 的匹配模式(正则表达式)。
  • Definition:镜像定义,主要有三个参数:ha-mode, ha-params, ha-sync-mode。
    • ha-mode:指明镜像队列的模式,有效值为 all、exactly、nodes。其中 all 表示在集群中所有的节点上进行镜像(默认即此);exactly 表示在指定个数的节点上进行镜像,节点的个数由 ha-params 指定;nodes 表示在指定的节点上进行镜像,节点名称通过 ha-params 指定。
    • ha-params:ha-mode 模式需要用到的参数。
    • ha-sync-mode:进行队列中消息的同步方式,有效值为 automatic 和 manual。
  • priority 为可选参数,表示 policy 的优先级。

配置完成后,点击下面的 add/update policy 按钮,完成策略的添加,如下:

添加完成后,我们可以进行一个简单的测试。

首先确认三个 RabbitMQ 都启动了,然后用上面的 provider 向消息队列发送一条消息。

发完之后关闭 mq01 实例。

接下来启动 consumer,此时发现 consumer 可以完成消息的消费(注意和前面的反向测试区分),这就说明镜像队列已经搭建成功了。

3.2 命令行配置镜像队列

命令行的配置格式如下:

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

举一个简单的配置案例:

rabbitmqctl set_policy -p / --apply-to queues my_queue_mirror "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

4. 小结

好啦,这就是松哥和大家分享的 RabbitMQ 中的集群搭建,感兴趣的小伙伴赶紧去试试吧~

手把手教你搭建 RabbitMQ 集群相关推荐

  1. 【超详细】手把手教你搭建MongoDB集群搭建

    MongoDB集群搭建 MongoDB集群简介 mongodb 集群搭建的方式有三种: 主从备份(Master - Slave)模式,或者叫主从复制模式. 副本集(Replica Set)模式 分片( ...

  2. redis 端口_「建议收藏」手把手教你搭建redis集群

    前言 在生产中单机的redis服务不能保证程序的高可用,所以有时需要我们来搭建一个redis集群,保证某一台redis服务挂了的时候,我们的服务还可以保证正常运行. 单机redis的搭建,可以参考我的 ...

  3. 手把手教你搭建Kubernetes集群

    文章内容输出来源:拉勾教育Java高薪训练营 一.初识拉勾教育 最开始并不知道拉勾有教育模块的业务,一直都以为只有招聘.直到今年5月份的时候拉勾的小姐姐打电话给我说他们有一个训练营问我是否有兴趣,那个 ...

  4. Docker:搭建RabbitMQ集群

    RabbitMQ原理介绍(一) RabbitMQ安装使用(二) RabbitMQ添加新用户并支持远程访问(三) RabbitMQ管理命令rabbitmqctl详解(四) RabbitMQ两种集群模式配 ...

  5. 搭建RabbitMQ集群

    下面以三台虚拟机为例,搭建RabbitMQ集群 首先在第一台上面安装完成RabbitMQ,然后克隆三台. 接下来修改主机名称,分别修改为node1,node2,node3 vim /etc/hostn ...

  6. 关于搭建rabbitmq集群报错Error: unable to perform an operation on node ‘rabbit@localhost‘. Please see diagnos

    项目场景: 搭建rabbitmq集群时mq1为主,mq2,mq3为从 mq2和mq3加入集群时输入命令:rabbitmqctl join_cluster rabbit@mq1报错 问题描述: 具体报错 ...

  7. Docker搭建RabbitMQ集群

    目录 1. 集群形成的要求 2. 集群中的节点 3. CLI如何验证节点 4. RabbitMQ集群搭建 5. Nginx实现负载均衡 6. 测试 集群形成的要求 ① 主机名解析 RabbitMQ节点 ...

  8. 手把手带你搭建redis集群

    redis-cluster是redis官方提供的分布式数据库解决方案,集群通过分片进行数据共享,并提供复制和故障转移功能. redis集群主要分为主节点和从节点.主节点用于处理槽,而从节点用于复制某个 ...

  9. k8s搭建 rabbitmq集群

    工具 版本 k8s 1.19 rabbitmq 3.7.8 rabbitmq镜像下载-CSDN mq镜像下载位置 链接:https://pan.baidu.com/s/1tJ1xxfA174Kjj4C ...

  10. Spring Cloud Alibaba:一步一步教你搭建Nacos集群

    架构图 3个或者3个以上Nacos才能构成集群 Nacos集群模式下,微服务节点并不直接访问Nacos,而是通过Nginx反向代理来访问 Nacos集群模式不能使用自带的derby存储,而是需要配置M ...

最新文章

  1. ESP32片上模数转换ADC精度简单测试方案及测试数据分享
  2. php怎么实现md5加密,php如何进行md5加密
  3. PHP-代码审计-变量覆盖
  4. Yum包管理工具的20个常用命令
  5. Win8.1/Win10在某些程序输入中文变成问号的解决方法
  6. JavaScript基础-基本数据类型和基本流程控制
  7. swwht(canvas).demo
  8. @Scope作用域代理的应用:@RefreshScope注解实现动态刷新配置的底层原理与实现
  9. Android学习分享:执行某ViewGroup的动画时,子控件太多导致动画执行卡顿的问题...
  10. CoolFire系列讲座 第2讲
  11. css设置div边框圆角,CSS圆角有立体感的DIV边框
  12. u盘复制到计算机的文档打不开怎么办,U盘文件复制到别的电脑打不开怎么办
  13. 【SpringMVC】DispatcherServlet重要组件之一MultipartResolver
  14. C++编写任意次clampedB样条曲线(曲线分别与第一个控制点和最后一个控制点的第一边和最后一边相切)
  15. javascript判断文本语言类型
  16. WIFI模块接入ONENET步骤
  17. 507 Lusir的游戏 二分 数论 [代码源][namomo spring camp]每日一题div2
  18. 无线发射芯片A7105在RF短距离通信的应用
  19. Vue框架背后的故事
  20. POI Exercise

热门文章

  1. mysql 关闭防火墙 命令_CentOS7关闭防火墙命令
  2. 尚德机构推出2019版CPA系列纸质书 配套小程序刷题
  3. Qt自定义DateTime控件--实现日历及时间选择器自定义
  4. OOC 面向对象C语言编程实践
  5. ftp 连接失败。500 OOPS: cannot change directory:
  6. Blast 几种方法的具体用法以及含义
  7. 记录手机app的使用时长
  8. react 实现图片的滚动缩放和按住鼠标左键移动图片效果
  9. 毕业实习感想—软件测试
  10. 为Onda v820w CH (v1) DualOS平板刷写Remix单系统