RabbitMQ集群与负载均衡实战指南

文章目录

  • 集群架构
    • 概述
    • 仲裁队列的使用
      • [1. 使用Spring框架代码创建](#1. 使用Spring框架代码创建)
      • [2. 使用amqp-client创建](#2. 使用amqp-client创建)
      • [3. 使用管理平台创建](#3. 使用管理平台创建)
  • 负载均衡
    • [引入HAProxy 负载均衡:](#引入HAProxy 负载均衡:)
    • 使用方法
      • [1. 修改配置文件](#1. 修改配置文件)
      • [2. 声明队列 test_cluster](#2. 声明队列 test_cluster)
      • [3. 发送消息](#3. 发送消息)

集群架构

概述

RabbitMQ支持部署多个结点,每个结点存储相同的数据,本质上没有区别。用户可以访问任意一个结点,其响应结果是一致的。每个结点都包含多个队列,队列的类型有很多,本博客主要探讨经典队列(Classic)和仲裁队列(Quorum)。不论什么类型的队列,都会存储两类消息:

  • 元数据:队列名称、交换机信息、绑定等
  • 消息数据:队列中存储的实际消息。

1. 经典队列(Classic Queues)

  • 特点
    • 元数据在集群所有节点共享,消息默认存储在主节点因此如果某个结点一旦宕机,对应存储的消息数据在该集群中将会丢失
    • 支持持久化(Durable)和非持久化。
    • 一致性较弱(最终一致性),性能高,灵活性强。
    • 适合通用场景,如任务分发、日志收集。

2. 仲裁队列(Quorum Queues)

  • 特点
    • 基于Raft 共识算法的高可用队列,消息数据会同步到集群中的其他节点,即使某个结点宕机,也能够保证集群的数据一致性。

    • 性能开销较高,不支持部分经典队列功能(如优先级)。

    • 适合对一致性要求高的场景,如金融交易、订单处理。

Raft 共识算法,这里用动画的方式形象的阐释了Raft保证数据一致性的执行流程,所以小编在这里偷个懒。

仲裁队列的使用

仲裁队列(Quorum Queue)是RabbitMQ中的一种高可用队列,它能够在节点故障时继续提供服务。以下是创建仲裁队列的三种方式:

1. 使用Spring框架代码创建

通过Spring的注解和配置,可以方便地创建仲裁队列。

java 复制代码
@Configuration
public class QuorumConfig {
    @Bean("quorumQueue")
    public Queue quorumQueue() {
        return QueueBuilder.durable("quorum_queue").quorum().build();
    }
}

2. 使用amqp-client创建

通过Java代码直接使用amqp-client库来创建仲裁队列。

java 复制代码
public class QuorumProducer {
    public static void main(String[] args) throws IOException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            
            Map<String, Object> param = new HashMap<>();
            param.put("x-queue-type", "quorum");
            channel.queueDeclare("quorum_queue", true, false, false, param);
        }
    }
}

3. 使用管理平台创建

通过RabbitMQ的管理平台,可以图形化地创建仲裁队列。


负载均衡

虽然RabbitMQ支持集群部署,看似好像提升了流量的承载力。但是如果请求只发送给一个或者那几个负载过高的结点,羊毛一直往一处薅,这个结点一旦挂掉,那么用户无法访问了!

解决办法------

引入HAProxy 负载均衡:

它和我们之前在Spirng中学的LoadBalence类似会把请求路由到正常的结点,并且个可以设定路由策略,充分利用每一个结点资源。

使用方法

在现代微服务架构中,负载均衡是确保服务高可用性和性能的关键技术之一。本文将介绍如何使用RabbitMQ实现负载均衡,并通过示例代码展示其具体实现步骤。

1. 修改配置文件

首先,需要修改RabbitMQ的配置文件,将HAProxy的IP和端口设置为RabbitMQ的绑定地址。

yaml 复制代码
spring:
  rabbitmq:
    addresses: amqp://study:study@124.71.229.73:15670/test

2. 声明队列 test_cluster

在Spring Boot应用中,我们需要声明一个队列,用于负载均衡。

java 复制代码
@Configuration
public class ClusterConfig {
    @Bean("ClusterQueue")
    public Queue clusterQueue() {
        return QueueBuilder.durable(Constant.CLUSTER_QUEUE).quorum().build();
    }
}

3. 发送消息

接下来,我们可以通过控制器发送消息到声明的队列。

java 复制代码
@RestController
@RequestMapping("/cluster")
public class ClusterController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping
    public String cluster() {
        rabbitTemplate.convertAndSend("", Constant.CLUSTER_QUEUE, "quorum test...");
        return "发送成功!";
    }
}

或者使用amqp客户端发送消息:

java 复制代码
public class ClusterProducer {
    private static final String QUEUE_NAME = "hello_world";

    public static void main(String[] args) throws IOException, TimeoutException {
        // 1. 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        // 2. 设置参数
        factory.setHost("124.71.229.73"); // HAProxy 地址
        factory.setPort(5670); // HAProxy 端口
        factory.setUsername("host"); // 用户名,默认
        factory.setPassword("study"); // 密码,默认
        // 3. 创建连接connection
        Connection connection = factory.newConnection();
        // 4. 创建channel通道
        Channel channel = connection.createChannel();
        // 5. 声明队列
        Map<String, Object> param = new HashMap<>();
        param.put("x-queue-type", "quorum");
        channel.queueDeclare("test_cluster", true, false, false, param);
        // 6. 通过channel发送消息到队列中
        String msg = "hello cluster...";
        // 简单模式下,使用的是默认交换机,使用默认交换机时,routingKey要和队列名称一致,才可以路由到对应的队列中去
        channel.basicPublish("", "test_cluster", null, msg.getBytes());
        // 7. 释放资源
        System.out.println("消息发送成功!");
        connection.close();
    }
}
相关推荐
蓝胖的四次元口袋30 分钟前
分布式知识梳理(4)
分布式
书香门第39 分钟前
系统设计练习 - 分布式黑名单服务(design a distributed denylist service)
分布式·系统架构·系统设计
江畔柳前堤8 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
霸道流氓气质13 小时前
RabbitMQ 延迟队列与死信队列:原理、实现与实战
分布式·rabbitmq·ruby
爱吃面的猫14 小时前
大数据Kafka3.x之——Kafka3.3.0安装与使用(详细)
大数据·分布式·zookeeper
小张同学a.1 天前
zabbix企业级监控平台4——分布式监控与grafana数据可视化
linux·运维·数据库·分布式·信息可视化·zabbix·grafana
番茄炒鸡蛋加糖1 天前
分布式 CAP、BASE 理论 & 中间件 CAP 取舍
分布式·中间件
海上小飞龙2 天前
Redis 分布式锁原理:从 SET NX EX 到 Redisson 看门狗
数据库·redis·分布式
明达智控技术2 天前
国产PLC、远程IO模块在食品包装机的应用
分布式·自动化
YOU OU2 天前
RabbitMQ应用问题
分布式·rabbitmq