RabbitMQ进阶之路:深入理解RabbitMQ核心概念

引言

在现代分布式系统中,消息传递是实现服务解耦、异步通信和流量削峰的关键技术。RabbitMQ 作为一个开源的消息中间件,基于 AMQP协议,提供了高效可靠的消息传递解决方案。本文将详细介绍 RabbitMQ 的基础概念和核心特性,帮助读者更好地理解和使用这一强大的消息代理工具。

1. RabbitMQ核心概念

1.1 AMQP(高级消息队列协议)

AMQP 是一种开放标准的应用层协议,专为异步、可靠、跨平台的消息通信而设计。它定义了消息中间件的核心组件模型和标准化交互规则,使不同系统之间能够通过统一协议实现高效的消息传递。

1.2 Virtual Hosts(虚拟主机)

Virtual Hosts是实体的逻辑分组,用于隔离不同的连接、交换器、队列、绑定、用户权限和策略。每个虚拟主机可以看作是一个独立的 RabbitMQ 服务器实例,允许多个租户在同一物理服务器上运行,彼此之间互不影响。

1.2 Producer(生产者)

生产者是负责创建并发送消息到RabbitMQ的服务。它通过AMQP协议与RabbitMQ服务器建立连接,并通过Channel通道发送消息。生产者将消息发送到交换器上,并使用路由键或消息头来决定消息的传递路径。

1.3 Consumer(消费者)

消费者是从消息队列中接收并处理消息的服务。它通过AMQP协议与RabbitMQ建立连接,并通过Channel通道从指定队列中获取消息,并根据业务逻辑完成对消息的处理。

1.4 Queue(队列)

队列是消息的有序集合,接收来自生产者的消息并将其保存。消息以FIFO(“先进先出”)的方式入队和出队(交付给消费者)。

1.5 Exchange(交换器)

交换器是发布者发布消息的实体,这些消息随后会被路由到一组队列或流中,交换器由使用客户端库的应用程序声明。交换器的目的是将流经它们的所有消息路由到一个或多个队列、流或其他交换器。

1.6 Binding(绑定)

绑定是连接Exchang和Queue的规则化链路,它通过绑定键(binding key)、头匹配(headers)或特定交换器类型约定的参数,明确规定了消息如何从交换器路由到目标队列。

1.7 Channel(通道)

Channel 是基于TCP连接的轻量级虚拟链路,允许在单个物理连接上创建多个独立的逻辑通信管道,每个通道可并行执行AMQP协议操作(如声明队列、发布消息、消费订阅等),实现资源复用与高效的多任务处理。

2. Exchange类型

2.1 Direct exchange(直连交换器)

2.1.1 核心原理

直连交换器是RabbitMQ 中一种核心的交换器类型,它根据消息的路由键(Routing Key)精确地将消息投递到一个或多个队列。只有当路由键完全匹配时,消息才会被投递。
在这里插入图片描述
在这种设置中,我们可以看到生产者通过指定路由键(orange、black、green)将消息发送至交换器,交换器根据队列绑定的绑定键精确匹配,将消息分发到对应的独立队列(Q1、Q2、Q3),最终由订阅特定队列的消费者处理。所有其他消息将被丢弃。

2.1.2 与Springboot集成

  1. 添加pom依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. 添加配置类
package com.example.rabbitmq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DirectExchangeConfig {

    // 定义Direct交换器名称
    public static final String DIRECT_EXCHANGE_NAME = "direct_exchange";
    // 定义队列名称Q1
    public static final String QUEUE_Q1_NAME = "queue.orange";
    // 定义队列名称Q2
    public static final String QUEUE_Q2_NAME = "queue.black";
    // 定义队列名称Q2
    public static final String QUEUE_Q3_NAME = "queue.green";

    /**
     * @return 返回一个名为direct_exchange直连交换器Bean
     */
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(DIRECT_EXCHANGE_NAME);
    }

    /**
     * @return 创建一个名为queue.orange队列Bean
     */
    @Bean
    public Queue queueOrange() {
        return new Queue(QUEUE_Q1_NAME);
    }

    /**
     * @return 创建一个名为queue.black队列Bean
     */
    @Bean
    public Queue queueBlack() {
        return new Queue(QUEUE_Q2_NAME);
    }

    /**
     * @return 创建一个名为queue.green队列Bean
     */
    @Bean
    public Queue queueGreen() {
        return new Queue(QUEUE_Q3_NAME);
    }

    /**
     * 通过绑定键 orange 将queueOrange绑定到交换器 directExchange
     *
     * @param directExchange
     * @param queueOrange
     * @return 创建一个Binding对象
     */
    @Bean
    public Binding bindingOrange(DirectExchange directExchange, Queue queueOrange) {
        return BindingBuilder.bind(queueOrange).to(directExchange).with("orange");
    }

    /**
     * 通过绑定键 black 将队列绑定到交换器 directExchange
     *
     * @param directExchange
     * @param queueBlack
     * @return
     */
    @Bean
    public Binding bindingBlack(DirectExchange directExchange, Queue queueBlack) {
        return BindingBuilder.bind(queueBlack).to(directExchange).with("black");
    }

    /**
     * 通过绑定键 green 将队列绑定到交换器 directExchange
     *
     * @param directExchange
     * @param queueGreen
     * @return
     */
    @Bean
    public Binding bindingGreen(DirectExchange directExchange, Queue queueGreen) {
        return BindingBuilder.bind(queueGreen).to(directExchange).with("green");
    }
}
  1. 添加生产者
package com.example.rabbitmq.producer;

import com.example.rabbitmq.config.DirectExchangeConfig;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DirectSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String routingKey, String message) {
        System.out.println("发送消息: '" + message + "' 路由键: " + routingKey);
        // 发送消息到direct_exchange交换器,并指定routing key
        rabbitTemplate.convertAndSend(DirectExchangeConfig.DIRECT_EXCHANGE_NAME, routingKey, message);
    }
}
  1. 添加消费者
package com.example.rabbitmq.consumer;

import com.example.rabbitmq.config.DirectExchangeConfig;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class DirectReceiver {

    /**
     * 监听queue.orange,如果有队列有消息时,就会自动调用该方法处理消息
     * @param message
     */
    @RabbitListener(queues = DirectExchangeConfig.QUEUE_Q1_NAME)
    public void receiveFromQ1(String message) {
        System.out.println("从队列 Q1接收消息: " + message);
    }

    @RabbitListener(queues = DirectExchangeConfig.QUEUE_Q2_NAME)
    public void receiveFromQ2(String message) {
        System.out.println("从队列 Q2接收消息: : " + message);
    }

    @RabbitListener(queues = DirectExchangeConfig.QUEUE_Q3_NAME)
    public void receiveFromQ3(String message) {
        System.out.println("从队列 Q3接收消息: : " + message);
    }
}
  1. 添加测试类
package com.example.rabbitmq;

import com.example.rabbitmq.producer.DirectSender;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Arrays;

@SpringBootTest
class RabbitMQApplicationTests {

    @Autowired
    private DirectSender directSender;

    @Test
    void contextLoads() {
    }

    @Test
    public void testSendDirectMessage(){
        Arrays.asList("orange", "black", "green").forEach(routingKey -> {
            directSender.sendMessage(routingKey, "hello world");
            System.out.println("已发送路由键: " + routingKey);
        });
    }
}

2.2 Fanout exchange(扇形交换器)

2.2.1 核心原理

扇形交换器是将消息路由到所有与之绑定的队列,并且会忽略路由键,如果有N个队列绑定到同一个扇形交换器,当有一条消息发送到该交换器时,消息会被广播到所有的N个队列。
在这里插入图片描述
在这种设置中,我们可以看到扇形交换器绑定了Q1、Q2、Q3三个队列,当生产者将消息发送到交换器时,队列Q1、Q2、Q3都会收到相同的消息并被对应的消费者处理。

2.2.2 与Springboot集成

  1. 添加配置类
package com.example.rabbitmq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FanoutExchangeConfig {

    // 定义Fanout交换器名称
    public static final String FANOUT_EXCHANGE_NAME = "fanout_exchange";

    // 定义队列名称Q1
    public static final String QUEUE_Q1_NAME  = "Q1";
    // 定义队列名称Q2
    public static final String QUEUE_Q2_NAME = "Q2";
    // 定义队列名称Q3
    public static final String QUEUE_Q3_NAME = "Q3";


    // 创建 Fanout Exchange
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(FANOUT_EXCHANGE_NAME);
    }

    // 创建队列 Q1
    @Bean
    public Queue queueFanout1() {
        return new Queue(QUEUE_Q1_NAME);
    }

    // 创建队列 Q2
    @Bean
    public Queue queueFanout2() {
        return new Queue(QUEUE_Q2_NAME);
    }

    @Bean
    public Queue queueFanout3() {
        return new Queue(QUEUE_Q3_NAME);
    }

    // 绑定 Q1 到 Fanout Exchange
    @Bean
    public Binding bindingFanout1(Queue queueFanout1, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(queueFanout1).to(fanoutExchange);
    }

    // 绑定 Q2 到 Fanout Exchange
    @Bean
    public Binding bindingFanout2(Queue queueFanout2, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(queueFanout2).to(fanoutExchange);
    }

    // 绑定 Q3 到 Fanout Exchange
    @Bean
    public Binding bindingFanout3(Queue queueFanout3, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(queueFanout3).to(fanoutExchange);
    }
}
  1. 添加生产者
package com.example.rabbitmq.producer;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class FanoutSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String message) {
        System.out.println("Sending message: " + message);
        rabbitTemplate.convertAndSend("fanout_exchange", "", message);
    }
}
  1. 添加消费者
package com.example.rabbitmq.consumer;

import com.example.rabbitmq.config.FanoutExchangeConfig;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class FanoutReceiver {
    // 监听队列 Q1
    @RabbitListener(queues = FanoutExchangeConfig.QUEUE_Q1_NAME)
    public void receiveFromQ1(String message) {
        System.out.println("Received from Q1: " + message);
    }

    // 监听队列 Q2
    @RabbitListener(queues = FanoutExchangeConfig.QUEUE_Q2_NAME)
    public void receiveFromQ2(String message) {
        System.out.println("Received from Q2: " + message);
    }

    // 监听队列 Q2
    @RabbitListener(queues = FanoutExchangeConfig.QUEUE_Q3_NAME)
    public void receiveFromQ3(String message) {
        System.out.println("Received from Q3: " + message);
    }
}
  1. 添加测试类
package com.example.rabbitmq;

import com.example.rabbitmq.producer.FanoutSender;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class RabbitMQApplicationTests {

    @Autowired
    private FanoutSender fanoutSender;

    @Test
    void contextLoads() {
    }

    @Test
    public void testSendFanoutMessage() {
        fanoutSender.sendMessage("hello world");
    }
}

2.3 Topic exchange(主题交换器)

2.3.1 核心原理

主题交换器是一种通过路由键(routing key)和绑定模式(binding pattern)的灵活匹配规则来路由消息的交换器类型。它允许生产者使用由点分隔的多单词路由键(如quick.white.rabbit),而消费者通过绑定队列时指定的通配符模式来筛选消息。这种机制使得Topic Exchange非常适合需要基于多维度条件(实现复杂消息分发的场景,提供了比Direct Exchange更强大、比Fanout Exchange更精确的路由控制。
在这里插入图片描述
通配符类型以及匹配规则

  • *:匹配 一个且仅一个 单词(单词间以 . 分隔)。
  • #:匹配 零个或多个 单词(单词间以 . 分隔)。
绑定键路由键是否匹配描述
*.orange.*quick.orange.rabbit中间单词匹配
*.*.rabbitlazy.white.rabbit最后单词匹配
lazy.#lazy.brown.foxlazy后匹配多个单词
*.orange.*orange.rabbit缺少第三个单词
*.*.rabbitlazy.white.elephant最后一个单词不匹配

2.3.2 与Springboot集成

  1. 添加配置类
package com.example.rabbitmq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TopicExchangeConfig {
    // 定义Topic交换器名称
    public static final String TOPIC_EXCHANGE_NAME = "topic_exchange";
    // 定义队列名称Q1
    public static final String QUEUE_Q1_NAME = "topic_Q1";
    // 定义队列名称Q2
    public static final String QUEUE_Q2_NAME = "topic_Q2";

    public static final String QUEUE_Q3_NAME = "topic_Q3";


    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(TOPIC_EXCHANGE_NAME);
    }

    // 定义队列名称topic_Q1
    @Bean
    public Queue queueTopic1() {
        return new Queue(QUEUE_Q1_NAME);
    }

    // 定义队列名称topic_Q2
    @Bean
    public Queue queueTopic2() {
        return new Queue(QUEUE_Q2_NAME);
    }

    // 定义队列名称topic_Q3
    @Bean
    public Queue queueTopic3() {
        return new Queue(QUEUE_Q3_NAME);
    }

    // 绑定队列到topic_exchange交换器,并指定路由键*.orange.*
    @Bean
    public Binding bindingQ1(Queue queueTopic1, TopicExchange topicExchange) {
        // 绑定键格式:user.*.notification(匹配一个中间词)
        return BindingBuilder.bind(queueTopic1)
                .to(topicExchange)
                .with("*.orange.*");
    }

    // 绑定队列到topic_exchange交换器,并指定路由键*"*.*.rabbit
    @Bean
    public Binding bindingQ2(Queue queueTopic2, TopicExchange topicExchange) {
        // 绑定键格式:user.*.notification(匹配一个中间词)
        return BindingBuilder.bind(queueTopic2)
                .to(topicExchange)
                .with("*.*.rabbit");
    }


    // 绑定队列到topic_exchange交换器,并指定路由键lazy.#
    @Bean
    public Binding bindingQ3(Queue queueTopic3, TopicExchange topicExchange) {
        // 绑定键格式:user.*.notification(匹配一个中间词)
        return BindingBuilder.bind(queueTopic3)
                .to(topicExchange)
                .with("lazy.#");
    }
}
  1. 添加生产者
package com.example.rabbitmq.producer;

import com.example.rabbitmq.config.TopicExchangeConfig;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TopicSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String message, String routingKey) {
        System.out.println("Sending message: " + message);
        rabbitTemplate.convertAndSend(TopicExchangeConfig.TOPIC_EXCHANGE_NAME, routingKey, message);
    }
}
  1. 添加消费者
package com.example.rabbitmq.consumer;

import com.example.rabbitmq.config.FanoutExchangeConfig;
import com.example.rabbitmq.config.TopicExchangeConfig;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class TopicReceiver {
    // 监听队列Q2
    @RabbitListener(queues = TopicExchangeConfig.QUEUE_Q1_NAME)
    public void receiveFromQ1(String message) {
        System.out.println("Received from Q1: " + message);
    }

    // 监听队列 Q2
    @RabbitListener(queues = TopicExchangeConfig.QUEUE_Q2_NAME)
    public void receiveFromQ2(String message) {
        System.out.println("Received from Q2: " + message);
    }

    @RabbitListener(queues = TopicExchangeConfig.QUEUE_Q3_NAME)
    public void receiveFromQ3(String message) {
        System.out.println("Received from Q3: " + message);
    }
}
  1. 添加测试类
package com.example.rabbitmq;

import com.example.rabbitmq.producer.TopicSender;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Arrays;

@SpringBootTest
class RabbitMQApplicationTests {

    @Autowired
    private TopicSender topicSender;

    @Test
    void contextLoads() {
    }

    @Test
    public void testSendTopicMessage() {
        Arrays.asList("quick.orange.rabbit", "lazy.orange.elephant", "quick.orange.fox", "quick.brown.fox").forEach(routingKey -> {
            topicSender.sendMessage("hello world", routingKey);
        });
    }
}

2.4 Headers exchange(头交换器)

2.4.1 核心原理

头交换器是一种通过消息头而非路由键来路由消息的交换器类型。它根据消息的 headers 属性(键值对)与绑定时设定的匹配规则(x-match: all 或 x-match: any)来决定投递到哪些队列。
在这里插入图片描述
匹配规则

  • x-match=all:消息头必须包含所有指定的键值对。
  • x-match=any:消息头只需包含任意一个指定的键值对。

2.4.2 与springboot集成

  1. 添加配置类
package com.example.rabbitmq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.HeadersExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class HeadersExchangeConfig {

    public static final String HEADERS_EXCHANGE_NAME = "headers-exchange";
    public static final String QUEUE_Q1_NAME = "queue_q1";
    public static final String QUEUE_Q2_NAME = "queue_q2";
    public static final String QUEUE_Q3_NAME = "queue_q3";

    // 创建HeadersExchange交换器
    @Bean
    public HeadersExchange headersExchange() {
        return new HeadersExchange(HEADERS_EXCHANGE_NAME);
    }

    // 创建Q1 Queue
    @Bean
    public Queue headersQueue1() {
        return QueueBuilder.durable(QUEUE_Q1_NAME).build();
    }

    // 创建Q2 Queue
    @Bean
    public Queue headersQueue2() {
        return new Queue(QUEUE_Q2_NAME);
    }

    // 创建Q3 Queue
    @Bean
    public Queue headersQueue3() {
        return new Queue(QUEUE_Q3_NAME);
    }

    // 绑定Q1与headers exchange并指定匹配规则,whereAll匹配所有key vaue
    @Bean
    public Binding bindingHeaderQ1(HeadersExchange headersExchange, Queue headersQueue1) {
        Map<String, Object> matchAll = new HashMap<>();
        matchAll.put("x-match", "all");
        matchAll.put("log_level", "error");
        matchAll.put("env", "prd");
        return BindingBuilder.bind(headersQueue1)
                .to(headersExchange)
                .whereAll(matchAll)
                .match();
    }

    // 绑定Q2与headers exchange并指定匹配规则,whereAny匹配一个即可
    @Bean
    public Binding bindingHeaderQ2(HeadersExchange headersExchange, Queue headersQueue2) {
        Map<String, Object> matchAny = new HashMap<>();
        matchAny.put("x-match", "any");
        matchAny.put("log_level", "info");
        matchAny.put("env", "test");
        return BindingBuilder.bind(headersQueue2)
                .to(headersExchange)
                .whereAny(matchAny)
                .match();
    }

    @Bean
    public Binding bindingHeaderQ3(HeadersExchange headersExchange, Queue headersQueue3) {
        Map<String, Object> matchAll = new HashMap<>();
        matchAll.put("x-match", "all");
        matchAll.put("priority", "high");
        matchAll.put("role", "user");
        return BindingBuilder.bind(headersQueue3)
                .to(headersExchange)
                .whereAll(matchAll)
                .match();
    }
}
  1. 添加生产者
package com.example.rabbitmq.producer;

import com.example.rabbitmq.config.HeadersExchangeConfig;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class HeadersSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String messageBody, Map<String, Object> headers) {
        // 构造消息头
        MessageProperties properties = new MessageProperties();
        headers.forEach(properties::setHeader);

        // 发送到 Headers Exchange(不需要 routing key)
        Message message = new Message(messageBody.getBytes(), properties);
        rabbitTemplate.send(HeadersExchangeConfig.HEADERS_EXCHANGE_NAME, "", message);
        System.out.println("Sent message: " + messageBody);
    }
}
  1. 添加消费者
package com.example.rabbitmq.consumer;

import com.example.rabbitmq.config.HeadersExchangeConfig;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class HeadersConsumer {

    @RabbitListener(queues = HeadersExchangeConfig.QUEUE_Q1_NAME)
    public void handleQ1(Message message) {
        String body = new String(message.getBody());
        System.out.println("Q1 Received: " + body);
        System.out.println("Headers: " + message.getMessageProperties().getHeaders());
    }

    @RabbitListener(queues = HeadersExchangeConfig.QUEUE_Q2_NAME)
    public void handleQ2(Message message) {
        String body = new String(message.getBody());
        System.out.println("Q2 Received: " + body);
        System.out.println("Headers: " + message.getMessageProperties().getHeaders());
    }

    @RabbitListener(queues = HeadersExchangeConfig.QUEUE_Q3_NAME)
    public void handleQ3(Message message) {
        String body = new String(message.getBody());
        System.out.println("Q3 Received: " + body);
        System.out.println("Headers: " + message.getMessageProperties().getHeaders());
    }
}
  1. 添加测试代码
package com.example.rabbitmq;

import com.example.rabbitmq.producer.HeadersSender;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest
class RabbitMQApplicationTests {

    @Autowired
    private HeadersSender headersSender;

    @Test
    void contextLoads() {
    }

    @Test
    public void testSendHeadersMessage() {
        Map<String, Object> headers1 = new HashMap<>();
        headers1.put("log_level", "error");
        headers1.put("env", "prd");
        headersSender.sendMessage("hello world", headers1);

        // 发送到队列2(满足 env=prod)
        Map<String, Object> headers2 = new HashMap<>();
        headers2.put("log_level", "info");
        headers2.put("env", "prd");
        headersSender.sendMessage("hello world", headers2);

        // 发送到队列3(满足 priority=high)
        Map<String, Object> headers3 = new HashMap<>();
        headers3.put("priority", "high");
        headers3.put("role", "admin");
        headersSender.sendMessage("hello world", headers3);

    }
}

3. 持久化

RabbitMQ的持久化是指将消息、队列和交换器的数据保存到磁盘,以确保在服务器重启后数据不会丢失。

3.1 消息持久化

消息持久化是指将消息写入磁盘存储,确保即使RabbitMQ服务重启,消息也不会丢失。但需注意,仅当队列本身也是持久化的,消息持久化才会生效,否则消息仍可能丢失。使用springboot集成rabbitmq可以通过MessageDeliveryMode.PERSISTENT设置来实现消息的持久化。

package com.example.rabbitmq.producer;

import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MessagePersistent {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String message) {
        rabbitTemplate.convertAndSend("exchange_name", "routing_key", message, msg -> {
            // 设置消息持久化
            msg.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
            return msg;
        });
    }
}

3.2 队列持久化

队列持久化是指将队列的元数据写入磁盘存储,当RabbitMQ服务重启,队列会自动重建,但是未消费的消息会丢失。使用springboot集成rabbitmq可以通过QueueBuilder.durable(“queue_name”).build()设置来实现队列的持久化。

@Bean
public Queue headersQueue1() {
    return QueueBuilder.durable("queue_name").build();
}

3.3 交换器持久化

交换器持久化是指将交换器的元数据写入磁盘存储,当RabbitMQ服务重启,交换器会自动重建。使用springboot集成rabbitmq可以通过QueueBuilder.durable(“queue_name”).build()设置来实现队列的持久化。

@Bean
public HeadersExchange headersExchange() {
    return ExchangeBuilder.headersExchange("exchange_name")
            .durable(true)
            .build();
}

4. 总结

RabbitMQ作为一款高效、可靠的消息中间件,通过生产者-消费者模型、队列、交换机和路由机制,实现了分布式系统的松耦合与异步通信。理解其核心概念是构建高可用、可扩展应用的基础。无论是解耦服务、流量削峰,还是实现跨系统协作,RabbitMQ都提供了优雅的解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值