RabbitMQ 集群_rabbitmq集群-程序员宅基地

技术标签: 容器  rabbitmq  docker  

一、RabbitMQ 集群介绍

1.1 两种模式

RabbitMQ 集群有两种模式:

  • 普通集群
  • 镜像集群

1.2 普通集群

普通集群模式,就是将 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.1 预备知识

  • 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="rabbitmq_cookie" rabbitmq

docker run -d --hostname rabbit02 --name mq02 -p 5672:5672 -p 15672:15672 --link mq01:mylink01 -e RABBITMQ_ERLANG_COOKIE="rabbitmq_cookie" rabbitmq

docker run -d --hostname rabbit03 --name mq03 -p 5673:5672 -p 15673:15672 --link mq01:mylink02 --link mq02:mylink03 -e RABBITMQ_ERLANG_COOKIE="rabbitmq_cookie" rabbitmq

mq02 和 mq03 分别使用了 --link 参数来实现容器连接。注意:mq03 容器既要能够连接 mq01,也要能够连接 mq02。

接下来开始集群的配置

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

docker exec -it mq02 /bin/bash
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit01
rabbitmqctl start_app

执行如下命令,将 mq03 容器加入到集群中:

docker exec -it mq03 /bin/bash
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit01
rabbitmqctl start_app

进入任意一个容器内,输入以下命令查看集群状态:

rabbitmqctl cluster_status

2.3 开启控制台界面

在每一个容器内,执行以下命令:

rabbitmq-plugins enable rabbitmq_management 

2.4 控制台界面点击Connection 提示 Stats in management UI are disabled on this node

进入容器内,以 mq01 为例,执行以下命令:

docker exec -it mq01 /bin/bash  # 进入容器
cd /etc/rabbitmq/conf.d/   # 进入容器内该目录下
echo management_agent.disable_metrics_collector = false > management_agent.disable_metrics_collector.conf
exit  # 退出当前容器
docker restart mq01  # 重启容器

在这里插入图片描述

2.5 代码测试

配置 application.yml,内容如下:

spring:
  rabbitmq:
    addresses: IP地址:5671,IP地址:5672,IP地址:5673
    username: guest
    password: guest

创建队列、交换机以及绑定关系

@Configuration
public class RabbitConfig {
    

    public static final String CLUSTER_EXCHANGE_NAME = "cluster_exchange_name";
    public static final String CLUSTER_QUEUE_NAME = "cluster_queue_name";
    public static final String CLUSTER_ROUTING_KEY = "cluster_routing_key";

    @Bean
    public Queue msgQueue(){
    
        return new Queue(CLUSTER_QUEUE_NAME, true, false, false, null);
    }

    @Bean
    public DirectExchange directExchange(){
    
        return new DirectExchange(CLUSTER_EXCHANGE_NAME, true, false);
    }

    @Bean
    public Binding queueBindingExchange(@Qualifier("msgQueue") Queue msgQueue,
                                        @Qualifier("directExchange") DirectExchange directExchange){
    
        return BindingBuilder.bind(msgQueue).to(directExchange).with(CLUSTER_ROUTING_KEY);
    }
}

接下来在单元测试中进行消息发送测试:

@SpringBootTest
class RabbitmqClusterApplicationTests {
    

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void contextLoads() {
    
        rabbitTemplate.convertAndSend(RabbitConfig.CLUSTER_EXCHANGE_NAME, RabbitConfig.CLUSTER_ROUTING_KEY, "你好");
    }

}

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

接下来创建消息消费者

@Component
public class RabbitConsumer {
    
    @RabbitListener(queues = RabbitConfig.CLUSTER_QUEUE_NAME)
    public void receiveMsg(Message msg){
    
        System.out.println("消息:" + new String(msg.getBody()));
    }
}

当消息消费者启动成功后,这个方法中只收到一条消息。
在这里插入图片描述

2.6 反向测试

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

使用以下命令停止 mq01 实例:

docker exec -it mq01 /bin/bash
rabbitmqctl stop_app

停止后重新启动 Consumer,会报如下错误

Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - home node 'rabbit@rabbit01' of durable queue 'cluster_queue_name' in vhost '/' is down or inaccessible, class-id=50, method-id=10)
	at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66) ~[amqp-client-5.14.2.jar:5.14.2]
	at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36) ~[amqp-client-5.14.2.jar:5.14.2]
	at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:502) ~[amqp-client-5.14.2.jar:5.14.2]
	at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:293) ~[amqp-client-5.14.2.jar:5.14.2]
	at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:141) ~[amqp-client-5.14.2.jar:5.14.2]
	... 20 common frames omitted

其他节点:
在这里插入图片描述

三、搭建镜像集群

镜像集群不需要额外搭建,只需要将队列配置为镜像队列即可。这个配置可以通过网页配置,也可以通过命令行配置。

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"}'

在这里插入图片描述

文章转载自:手把手教你搭建 RabbitMQ 集群

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dingd1234/article/details/125247546

智能推荐

【雕爷学编程】Arduino动手做(208)---使用Beetle ESP32 C3控制8X32位WS2812硬屏_esp32控制ws2812-程序员宅基地

文章浏览阅读294次。雕爷学编程,Arduino动手做,开源硬件,创客传感器,Beetle ESP32 C3开发板_esp32控制ws2812

python基础例题:删除列表中所有的素数_编写程序,删除列表中的所有素数-程序员宅基地

文章浏览阅读1.5w次,点赞6次,收藏23次。编写程序,删除列表中所有的素数(代码如下):arr = [12,3,62,7,91,67,27,45,6]for element in arr: tag=True # 质数大于 1 if element > 1: # 查看因子 for i in range(2, element): if (element % i) == 0: tag=False bre_编写程序,删除列表中的所有素数

Ubuntu20.04运行VINS-Fusion-程序员宅基地

文章浏览阅读932次。参考 https://blog.csdn.net/xiaojinger_123/article/details/121517771 修改代码。注意运行时每个终端都需要设置一次工作空间。_ubuntu20.04运行vins-fusion

ReactNative图标库 _ react-native-vector-icons 配置和使用-程序员宅基地

文章浏览阅读2.7k次。图标库地址https://github.com/oblador/react-native-vector-icons步骤一:下载图标库//要是安装报错,就再执行一次 npm install --save react-native-vector-icons步骤二:在android/app/build.gradle引入配置project.ext.vectoricons = [ iconFontNames: [ 'MaterialIcons.ttf', 'EvilIcons.ttf' ] _react-native-vector-icons

Java EasyPoi 模板导出Excel 图片不显示问题_easypoi imageentity-程序员宅基地

文章浏览阅读1.7k次,点赞2次,收藏2次。一开始无论setHeight 和 setWidth设置什么值图片都无法显示,后来发现设置了setRowspan 和 setColspan 且参数都要大于2才能将图片显示出来,图片虽然出来了,但是格式是不满足要求的,因为会合并别的单元格。总结来说就是easypoi的4.3.0版本导致的问题,将项目的版本号降到4.2.0后只需要设置Height和Width的值问题就解决了。其中setHeight() 和 setWidth() 的方法是设置图片的高和宽。一开始在导出图片到excel的时候图片会显示不出来。_easypoi imageentity

生产环境实施 VMware 虚拟化基础架构,千万不要犯 4 个错误_vmware workstation 为什么不能用在生产环境-程序员宅基地

文章浏览阅读947次。生产环境实施 VMware 虚拟化基础架构,千万不要犯 4 个错误https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&mid=2650630439&idx=1&sn=d08ec1dee816b3c8f36ba495daf842bd&chksm=bef917a1898e9eb7b1f75737dcd1182c5af03300bc687af6a8b2366ccbf8f092fdd3410295ca&scene=21#we_vmware workstation 为什么不能用在生产环境

随便推点

java学习路线_在整个业务运营系统实施过程中强调:统一标准是基础,数据集成是手段,优化资源是目-程序员宅基地

文章浏览阅读1k次。自己在一个培训机构的网站上面看到java的学习路线,觉得挺好的,分享给大家,希望对大家的学习有所帮助。第一阶段Java语言基础Java语言概述、Java环境配置、基本语法、Java流程控制语句、常用数据结构掌握常见的数据结构和实用算法;培养良好的企业级编程习惯。Java面向对象Java类设计、高级类特性(封装、继承、多态)、异常处理、Java集合、泛_在整个业务运营系统实施过程中强调:统一标准是基础,数据集成是手段,优化资源是目

模型转换 PyTorch转ONNX 入门-程序员宅基地

文章浏览阅读1w次,点赞31次,收藏177次。本文主要介绍如何将PyTorch模型转换为ONNX模型,为后面的模型部署做准备。转换后的xxx.onnx模型,进行加载和测试。最后介绍使用Netron,可视化ONNX模型,看一下网络结构;查看使用了那些算子,以便开发部署。目录前言一、PyTorch模型转ONNX模型1.1 转换为ONNX模型且加载权重1.2 转换为ONNX模型但不加载权重1.3 torch.onnx.export() 函数二、加载ONNX模型三、可视化ONNX模型。_pytorch转onnx

VINS-Mono-IMU预积分 (八:预积分代码带读+对应推导公式)_vins中的与积分约束代码-程序员宅基地

文章浏览阅读249次。这个雅可比的作为是为了在零偏 $b_{a},b_{w}$ 在经过优化数值发生变化后不需要再重新进行预积分,因为实际上 $k+1$ 时刻的预积分是用 $k$ 时刻的零偏 $b$ 来进行的,当经过优化后 $k+1$ 时刻的零偏 $b$ 就会发生变化,理论上 $k+1$ 时刻的预积分应该是用 $k+1$ 时刻的零偏 $b$ 来进行才对,由于是优化后才获得,但是重新进行预积分又非常耗时,所以采用 $f(x+Δb)=f(x)+J^{x}_{b}·Δb$ 这样的方式来进行近似更新,从这个公式可以看出里面就必须要对零偏_vins中的与积分约束代码

SSM框架实战系列之十三_H-ui框架之一-程序员宅基地

文章浏览阅读1.3w次,点赞9次,收藏70次。SSM框架实战系列之十三_H-ui框架之一_h-ui

CentOS 7系统安装时不能进入图形化安装界面_centos7进不了安装界面-程序员宅基地

文章浏览阅读2.5k次。在安装界面1、光标选中“install centos 7”2、按键盘"TAB"键3、在内容的最后一行末尾添加上 nodomeset原因:centos7安装包里自带的显卡驱动不支持主机上的显卡*,nodomeset表示不加载centos7安装包里的显卡驱动显卡*:年代久远的显卡,比如N卡的405,centos7 2009安装包;它两组合在一起时不能进入图像安装界面,需要添加nodomeset参数禁用安装包的显卡驱动..._centos7进不了安装界面

softmax函数实现(C语言)_softmax函数c语言实现-程序员宅基地

文章浏览阅读2.4k次,点赞6次,收藏10次。关于softmax函数:https://www.cnblogs.com/alexanderkun/p/8098781.htmlC语言实现:#include "stdio.h"#include "math.h"void main(void){ int i = 0; double sum = 0; int vertor0[6] = {1,2,3,4,5,6}; //初始向..._softmax函数c语言实现

推荐文章

热门文章

相关标签