引言
在现代分布式系统中,消息传递是实现服务解耦、异步通信和流量削峰的关键技术。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集成
- 添加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>
- 添加配置类
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");
}
}
- 添加生产者
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);
}
}
- 添加消费者
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);
}
}
- 添加测试类
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集成
- 添加配置类
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);
}
}
- 添加生产者
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);
}
}
- 添加消费者
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);
}
}
- 添加测试类
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 | ✅ | 中间单词匹配 |
*.*.rabbit | lazy.white.rabbit | ✅ | 最后单词匹配 |
lazy.# | lazy.brown.fox | ✅ | lazy后匹配多个单词 |
*.orange.* | orange.rabbit | ❌ | 缺少第三个单词 |
*.*.rabbit | lazy.white.elephant | ❌ | 最后一个单词不匹配 |
2.3.2 与Springboot集成
- 添加配置类
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.#");
}
}
- 添加生产者
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);
}
}
- 添加消费者
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);
}
}
- 添加测试类
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集成
- 添加配置类
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();
}
}
- 添加生产者
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);
}
}
- 添加消费者
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());
}
}
- 添加测试代码
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都提供了优雅的解决方案。