RabbitMQ 是一个开源的消息代理中间件,基于 AMQP 协议实现,支持多种消息模式和分布式部署。下面我将带你实现一个完整的 RabbitMQ 集成示例,并详细分析其功能和应用场景。
一、创建 Spring Boot 项目
-
使用 Spring Initializr
访问 Spring Initializr,配置以下参数:- Project:Maven Project
- Language:Java
- Spring Boot:3.0.x (或最新稳定版)
- Dependencies:
- Spring Web
- Spring AMQP (RabbitMQ)
- Lombok (可选)
-
手动添加依赖(如果需要)
在pom.xml
中确保以下依赖存在:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
二、配置 RabbitMQ 连接
在src/main/resources/application.properties
中添加 RabbitMQ 配置:
# RabbitMQ连接配置
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
# 可选配置
spring.rabbitmq.virtual-host=/
spring.rabbitmq.listener.simple.retry.enabled=true # 开启消费重试
spring.rabbitmq.listener.simple.retry.max-attempts=3 # 最大重试次数
三、定义消息模型
在src/main/java/com/example/rabbitmqdemo/model
包下创建消息类:
package com.example.rabbitmqdemo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderMessage implements Serializable {
private static final long serialVersionUID = 1L;
private String orderId;
private String productName;
private double amount;
}
四、配置队列、交换器和绑定
在src/main/java/com/example/rabbitmqdemo/config
包下创建配置类:
package com.example.rabbitmqdemo.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
// 定义队列名称
public static final String QUEUE_ORDER = "queue.order";
public static final String QUEUE_LOG = "queue.log";
// 定义交换器名称
public static final String EXCHANGE_TOPIC = "exchange.topic";
// 定义路由键
public static final String ROUTING_KEY_ORDER = "order.#";
public static final String ROUTING_KEY_LOG = "log.#";
// 创建队列
@Bean
public Queue orderQueue() {
return new Queue(QUEUE_ORDER, true); // 持久化队列
}
@Bean
public Queue logQueue() {
return new Queue(QUEUE_LOG, true);
}
// 创建主题交换器
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(EXCHANGE_TOPIC, true, false);
}
// 绑定队列到交换器
@Bean
public Binding bindingOrder() {
return BindingBuilder.bind(orderQueue()).to(topicExchange()).with(ROUTING_KEY_ORDER);
}
@Bean
public Binding bindingLog() {
return BindingBuilder.bind(logQueue()).to(topicExchange()).with(ROUTING_KEY_LOG);
}
}
五、消息生产者
在src/main/java/com/example/rabbitmqdemo/producer
包下创建生产者:
package com.example.rabbitmqdemo.producer;
import com.example.rabbitmqdemo.config.RabbitMQConfig;
import com.example.rabbitmqdemo.model.OrderMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class OrderProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送订单消息
*/
public void sendOrderMessage(OrderMessage message) {
// 发送消息到主题交换器,使用order相关路由键
rabbitTemplate.convertAndSend(
RabbitMQConfig.EXCHANGE_TOPIC,
"order.create", // 路由键
message
);
System.out.println("订单消息已发送: " + message);
}
/**
* 发送日志消息
*/
public void sendLogMessage(String logMessage) {
// 发送消息到主题交换器,使用log相关路由键
rabbitTemplate.convertAndSend(
RabbitMQConfig.EXCHANGE_TOPIC,
"log.info", // 路由键
logMessage
);
System.out.println("日志消息已发送: " + logMessage);
}
}
六、消息消费者
在src/main/java/com/example/rabbitmqdemo/consumer
包下创建消费者:
package com.example.rabbitmqdemo.consumer;
import com.example.rabbitmqdemo.config.RabbitMQConfig;
import com.example.rabbitmqdemo.model.OrderMessage;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class MessageConsumer {
/**
* 消费订单消息
*/
@RabbitListener(queues = RabbitMQConfig.QUEUE_ORDER)
public void handleOrderMessage(OrderMessage message) {
System.out.println("收到订单消息: " + message);
// 处理订单业务逻辑
}
/**
* 消费日志消息
*/
@RabbitListener(queues = RabbitMQConfig.QUEUE_LOG)
public void handleLogMessage(String message) {
System.out.println("收到日志消息: " + message);
// 处理日志业务逻辑
}
}
七、创建 Controller 测试接口
在src/main/java/com/example/rabbitmqdemo/controller
包下创建控制器:
package com.example.rabbitmqdemo.controller;
import com.example.rabbitmqdemo.model.OrderMessage;
import com.example.rabbitmqdemo.producer.OrderProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
@RestController
@RequestMapping("/api/rabbitmq")
public class RabbitMQController {
@Autowired
private OrderProducer orderProducer;
/**
* 测试发送订单消息
*/
@GetMapping("/sendOrder")
public String sendOrder() {
OrderMessage message = new OrderMessage(
UUID.randomUUID().toString(),
"iPhone 15",
8999.00
);
orderProducer.sendOrderMessage(message);
return "订单消息已发送";
}
/**
* 测试发送日志消息
*/
@GetMapping("/sendLog")
public String sendLog() {
orderProducer.sendLogMessage("用户登录成功 [user=admin]");
return "日志消息已发送";
}
}
八、RabbitMQ 的使用场景
-
异步处理
- 将耗时操作(如文件处理、邮件发送)放入消息队列,主线程立即返回响应
- 提高系统吞吐量和响应速度
-
系统解耦
- 服务间通过消息队列通信,无需直接依赖
- 新服务可以轻松接入现有系统
-
流量削峰
- 在高并发场景下,通过消息队列缓冲请求,避免系统过载
- 典型场景:秒杀活动、订单提交
-
日志收集
- 将分布式系统中的日志发送到消息队列,统一收集和处理
- 解耦日志处理和业务逻辑
-
事件驱动架构
- 基于消息队列实现事件发布 - 订阅模式
- 实现微服务间的事件驱动通信
-
数据同步
- 通过消息队列实现不同数据库间的数据同步
- 确保数据最终一致性
九、RabbitMQ 的核心功能
-
多种消息模式
- 点对点(P2P):一个生产者对应一个消费者
- 发布 - 订阅(Pub/Sub):一个生产者对应多个消费者
- 路由模式(Routing):根据路由键分发消息
- 主题模式(Topics):基于主题匹配分发消息
- 头部模式(Headers):基于消息头属性分发消息
-
消息持久化
- 确保消息在服务器重启后不丢失
- 通过将队列和消息标记为持久化实现
-
消息确认机制
- 生产者确认:确保消息成功发送到交换器
- 消费者确认:确保消息被成功处理
- 支持自动确认和手动确认模式
-
死信队列(DLQ)
- 处理无法被正常消费的消息
- 常见场景:消息重试多次仍失败、消息过期
-
优先级队列
- 支持为消息设置优先级,高优先级消息优先处理
- 适用于需要优先处理紧急任务的场景
-
负载均衡
- 通过多个消费者实现消息的负载均衡
- 确保系统资源被合理利用
十、测试和验证
-
启动 RabbitMQ 服务器
bash
rabbitmq-server
-
启动 Spring Boot 应用
运行主应用类的main
方法。 -
测试消息发送
访问以下 URL 触发消息发送:http://localhost:8080/api/rabbitmq/sendOrder
http://localhost:8080/api/rabbitmq/sendLog
-
查看控制台输出
确认消费者正确接收并处理了消息。
十一、注意事项
-
消息幂等性
- 由于网络波动等原因,消息可能会重复发送,消费端需保证幂等性
-
消息顺序性
- 默认情况下,RabbitMQ 不保证消息顺序
- 如果需要顺序性,可通过绑定到同一个队列的单个消费者实现
-
性能调优
- 合理配置连接池大小和并发消费者数量
- 使用批量发送和异步确认提高吞吐量
-
监控与管理
- 使用 RabbitMQ 管理界面监控队列状态和性能指标
- 设置告警机制,及时发现和处理异常情况