# SpringBoot集成RabbitMQ企业级实战教程
本文将从零开始,基于 IntelliJ IDEA 2023 Ultimate 版,搭建企业级的 SpringBoot-RabbitMQ 项目,涵盖 RabbitMQ 核心用法和企业级特性,所有代码可直接复制使用,适合新手快速上手并落地到生产环境。
# 1. 开发环境准备
# 1.1 环境清单(企业级标准配置)
| 工具/框架 | 版本号 | 备注 |
|---|---|---|
| IntelliJ IDEA | 2023 Ultimate | 项目管理和代码开发 |
| JDK | 17 | SpringBoot 3.x 最低要求 |
| SpringBoot | 3.5.10 | 核心开发框架 |
| Maven | 3.9.4 | 项目构建和依赖管理 |
| RabbitMQ | 3.13.2 | 消息中间件 |
| 操作系统 | Windows/MacOS | 无特殊限制 |
# 1.2 RabbitMQ 安装与验证(Docker 快速部署)
企业级环境推荐使用 Docker 部署 RabbitMQ(含管理插件),命令如下:
# 拉取 RabbitMQ 3.13.2 镜像(带管理插件)
docker pull rabbitmq:3.13.2-management
# 启动容器(映射端口、配置用户名密码,与你提供的信息对齐)
docker run -d --name rabbitmq-server \
-p 2765:5672 \ # AMQP 协议端口(映射为你指定的2765)
-p 15672:15672 \ # 管理界面端口
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=Admin@1029384756 \
rabbitmq:3.13.2-management
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
验证安装:
- 访问 RabbitMQ 管理界面:
http://localhost:15672(你的地址+管理端口) - 输入用户名
admin、密码Admin@1029384756,能登录则说明部署成功。
# 2. 项目初始化(IDEA 操作)
# 2.1 新建 SpringBoot 项目

# 2.2 验证 Maven 配置
项目根目录的 pom.xml 需包含以下核心依赖(自动生成,确认版本即可):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cc.hep</groupId>
<artifactId>SpringBoot-RabbitMQ</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBoot-RabbitMQ</name>
<description>SpringBoot集成RabbitMQ企业级项目</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- RabbitMQ 核心依赖 -->
<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>
<!-- RabbitMQ 测试依赖 -->
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Jackson(Spring Boot 默认包含,这里显式声明确保版本) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 3. RabbitMQ 核心配置(企业级规范)
# 3.1 应用配置文件(application.yml)
在 src/main/resources 下创建 application.yml,配置 RabbitMQ 连接信息和企业级参数(连接池、消费策略等):
spring:
# RabbitMQ 核心配置
rabbitmq:
host: localhost # 你的RabbitMQ地址
port: 2765 # 你的RabbitMQ端口
username: admin # 用户名
password: Admin@1029384756 # 密码
virtual-host: / # 虚拟主机(默认/)
# 增强连接稳定性配置
connection-timeout: 30000 # 增加连接超时到30秒
requested-heartbeat: 60 # 心跳间隔60秒(防止超时断开)
# 连接池配置
cache:
mode: CONNECTION
connection:
size: 5 # 减少连接池大小,避免过多连接
mode: CONNECTION
channel:
checkout-timeout: 30000 # 通道获取超时
# 自动重连配置
template:
retry:
enabled: true # 开启发送重试
max-attempts: 3 # 最大重试次数
initial-interval: 1000 # 初始重试间隔1秒
# 消费端配置(企业级核心:手动ACK,避免消息丢失)
listener:
simple:
acknowledge-mode: manual # 手动确认消息
concurrency: 3 # 减少消费线程数(从5减到3)
max-concurrency: 5 # 最大消费线程数
prefetch: 5 # 减少预取数量(从10减到5)
retry:
enabled: true # 开启消费重试
max-attempts: 3 # 最大重试次数
initial-interval: 2000 # 首次重试间隔(2秒)
# 自动恢复配置
auto-startup: true # 自动启动消费者
missing-queues-fatal: false # 队列不存在时不致命
recovery-interval: 5000 # 恢复间隔5秒
# 自定义RabbitMQ常量
rabbitmq:
exchange:
direct: "hep.direct.exchange"
topic: "hep.topic.exchange"
queue:
normal: "hep.normal.queue"
dead: "hep.dead.queue"
routing-key:
normal: "hep.normal.routing.key"
dead: "hep.dead.routing.key"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 3.2 RabbitMQ 核心配置类(企业级声明)
在 cc.hep.config 包下创建 RabbitMQConfig,用于声明交换机、队列、绑定关系(企业级规范:代码声明而非手动创建):
package cc.hep.config;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* RabbitMQ 核心配置类(企业级规范:声明交换机、队列、绑定关系)
*/
@Configuration
public class RabbitMQConfig {
// 从配置文件读取常量
@Value("${rabbitmq.exchange.direct}")
private String directExchange;
@Value("${rabbitmq.exchange.topic}")
private String topicExchange;
@Value("${rabbitmq.queue.normal}")
private String normalQueue;
@Value("${rabbitmq.queue.dead}")
private String deadQueue;
@Value("${rabbitmq.routing-key.normal}")
private String normalRoutingKey;
@Value("${rabbitmq.routing-key.dead}")
private String deadRoutingKey;
/**
* 1. 声明直连交换机(企业级常用:精准路由)
*/
@Bean
public DirectExchange directExchange() {
// durable: 持久化(重启RabbitMQ不丢失)
// autoDelete: 自动删除(无队列绑定时删除,企业级一般设为false)
return new DirectExchange(directExchange, true, false);
}
/**
* 2. 声明主题交换机(企业级常用:模糊路由)
*/
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(topicExchange, true, false);
}
/**
* 3. 声明普通队列(绑定死信配置,企业级防消息丢失)
*/
@Bean
public Queue normalQueue() {
return QueueBuilder.durable(normalQueue)
// 配置死信交换机
.deadLetterExchange(directExchange)
// 配置死信路由键
.deadLetterRoutingKey(deadRoutingKey)
// 队列消息过期时间(30秒,可选)
.ttl(30000)
.build();
}
/**
* 4. 声明死信队列(企业级必配:处理消费失败的消息)
*/
@Bean
public Queue deadQueue() {
return QueueBuilder.durable(deadQueue).build();
}
/**
* 5. 绑定普通队列到直连交换机
*/
@Bean
public Binding normalQueueBinding() {
return BindingBuilder.bind(normalQueue()).to(directExchange()).with(normalRoutingKey);
}
/**
* 6. 绑定死信队列到直连交换机
*/
@Bean
public Binding deadQueueBinding() {
return BindingBuilder.bind(deadQueue()).to(directExchange()).with(deadRoutingKey);
}
/**
* 7. 消息转换器(企业级:JSON格式序列化,避免序列化问题)
*/
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
/**
* 8. 配置RabbitTemplate(企业级:消息发送确认、返回确认)
*/
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter());
// 开启消息发送确认(确认消息是否到达交换机)
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
// 企业级处理:记录日志、告警、重试
System.err.println("消息发送到交换机失败:" + cause);
}
});
// 开启消息返回确认(确认消息是否到达队列)
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnsCallback(returnedMessage -> {
// 企业级处理:记录日志、告警、重试
System.err.println("消息发送到队列失败:" + returnedMessage.getReplyText());
});
return rabbitTemplate;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# 4. 生产者实现(企业级封装)
# 4.1 消息发送工具类(通用封装)
在 cc.hep.util 包下创建 RabbitMQProducerUtil,封装通用的消息发送方法(企业级:避免重复代码,统一处理发送逻辑):
package cc.hep.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
/**
* RabbitMQ 生产者工具类(企业级通用封装)
*/
@Component
public class RabbitMQProducerUtil {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private MessageConverter messageConverter;
@Autowired
private ObjectMapper objectMapper;
/**
* 发送普通消息(通用方法)
* @param exchange 交换机
* @param routingKey 路由键
* @param message 消息内容(任意对象)
*/
public void sendMessage(String exchange, String routingKey, Object message) {
try {
// 企业级:设置唯一消息ID(用于幂等、追踪)
String messageId = UUID.randomUUID().toString();
org.springframework.amqp.core.Message amqpMessage = messageConverter.toMessage(message, new org.springframework.amqp.core.MessageProperties());
amqpMessage.getMessageProperties().setMessageId(messageId);
// 发送消息
rabbitTemplate.send(exchange, routingKey, amqpMessage);
// 使用 Jackson 序列化消息内容
String jsonContent = objectMapper.writeValueAsString(message);
System.out.println("消息发送成功,ID:" + messageId + ",内容:" + jsonContent);
} catch (Exception e) {
// 企业级处理:记录异常、重试、告警
System.err.println("消息发送失败:" + e.getMessage());
throw new RuntimeException("消息发送失败", e);
}
}
/**
* 发送延迟消息(基于死信队列实现,企业级常用)
* @param exchange 交换机
* @param routingKey 路由键
* @param message 消息内容
* @param delayTime 延迟时间(毫秒)
*/
public void sendDelayMessage(String exchange, String routingKey, Object message, long delayTime) {
try {
String messageId = UUID.randomUUID().toString();
org.springframework.amqp.core.MessageProperties properties = new org.springframework.amqp.core.MessageProperties();
properties.setMessageId(messageId);
// 设置消息延迟时间(覆盖队列的默认TTL)
properties.setExpiration(String.valueOf(delayTime));
org.springframework.amqp.core.Message amqpMessage = messageConverter.toMessage(message, properties);
// 发送延迟消息
rabbitTemplate.send(exchange, routingKey, amqpMessage);
// 使用 Jackson 序列化消息内容
String jsonContent = objectMapper.writeValueAsString(message);
System.out.println("延迟消息发送成功,ID:" + messageId + ",延迟时间:" + delayTime + "ms,内容:" + jsonContent);
} catch (Exception e) {
System.err.println("延迟消息发送失败:" + e.getMessage());
throw new RuntimeException("延迟消息发送失败", e);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# 4.2 业务层生产者(模拟企业业务)
在 cc.hep.service 包下创建 RabbitMQProducerService,封装业务相关的消息发送逻辑:
package cc.hep.service;
import cc.hep.util.RabbitMQProducerUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* 消息生产者业务层(模拟企业级业务场景)
*/
@Service
public class RabbitMQProducerService {
@Autowired
private RabbitMQProducerUtil rabbitMQProducerUtil;
// 从配置文件读取常量
@Value("${rabbitmq.exchange.direct}")
private String directExchange;
@Value("${rabbitmq.routing-key.normal}")
private String normalRoutingKey;
/**
* 发送普通业务消息(例如:订单创建消息)
* @param orderId 订单ID
* @param orderName 订单名称
*/
public void sendOrderMessage(String orderId, String orderName) {
// 模拟订单对象(企业级:使用实体类)
OrderMessage orderMessage = new OrderMessage();
orderMessage.setOrderId(orderId);
orderMessage.setOrderName(orderName);
orderMessage.setCreateTime(System.currentTimeMillis());
// 发送消息
rabbitMQProducerUtil.sendMessage(directExchange, normalRoutingKey, orderMessage);
}
/**
* 发送延迟业务消息(例如:订单超时未支付提醒)
* @param orderId 订单ID
* @param delayTime 延迟时间(毫秒)
*/
public void sendDelayOrderMessage(String orderId, long delayTime) {
DelayOrderMessage delayOrderMessage = new DelayOrderMessage();
delayOrderMessage.setOrderId(orderId);
delayOrderMessage.setRemindContent("订单超时未支付,请及时处理");
// 发送延迟消息
rabbitMQProducerUtil.sendDelayMessage(directExchange, normalRoutingKey, delayOrderMessage, delayTime);
}
// 内部静态类:订单消息实体(企业级:单独创建实体类)
public static class OrderMessage {
private String orderId;
private String orderName;
private long createTime;
// getter/setter
public String getOrderId() { return orderId; }
public void setOrderId(String orderId) { this.orderId = orderId; }
public String getOrderName() { return orderName; }
public void setOrderName(String orderName) { this.orderName = orderName; }
public long getCreateTime() { return createTime; }
public void setCreateTime(long createTime) { this.createTime = createTime; }
}
// 内部静态类:延迟订单消息实体
public static class DelayOrderMessage {
private String orderId;
private String remindContent;
// getter/setter
public String getOrderId() { return orderId; }
public void setOrderId(String orderId) { this.orderId = orderId; }
public String getRemindContent() { return remindContent; }
public void setRemindContent(String remindContent) { this.remindContent = remindContent; }
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# 4.3 控制器(提供接口测试)
在 cc.hep.controller 包下创建 RabbitMQController,提供 HTTP 接口供外部调用(模拟企业级接口调用场景):
package cc.hep.controller;
import cc.hep.service.RabbitMQProducerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* RabbitMQ 测试控制器(企业级:提供接口供外部系统调用)
*/
@RestController
public class RabbitMQController {
@Autowired
private RabbitMQProducerService rabbitMQProducerService;
/**
* 发送普通订单消息
* @param orderId 订单ID
* @param orderName 订单名称
* @return 响应结果
*/
@GetMapping("/send/order")
public String sendOrderMessage(@RequestParam String orderId, @RequestParam String orderName) {
try {
rabbitMQProducerService.sendOrderMessage(orderId, orderName);
return "普通订单消息发送成功,订单ID:" + orderId;
} catch (Exception e) {
return "普通订单消息发送失败:" + e.getMessage();
}
}
/**
* 发送延迟订单消息
* @param orderId 订单ID
* @param delayTime 延迟时间(毫秒)
* @return 响应结果
*/
@GetMapping("/send/delay/order")
public String sendDelayOrderMessage(@RequestParam String orderId, @RequestParam long delayTime) {
try {
rabbitMQProducerService.sendDelayOrderMessage(orderId, delayTime);
return "延迟订单消息发送成功,订单ID:" + orderId + ",延迟时间:" + delayTime + "ms";
} catch (Exception e) {
return "延迟订单消息发送失败:" + e.getMessage();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 5. 消费者实现(企业级消费策略)
# 5.1 普通消息消费者(手动ACK)
在 cc.hep.consumer 包下创建 NormalMessageConsumer,处理普通队列的消息(企业级:手动ACK,异常处理,重试机制):
package cc.hep.consumer;
import cc.hep.service.RabbitMQProducerService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
/**
* 普通消息消费者(企业级:手动ACK,异常处理)
*/
@Component
public class NormalMessageConsumer {
@Autowired
private ObjectMapper objectMapper;
/**
* 消费普通队列消息
* @param message 消息体
* @param channel 通道(用于手动ACK)
* @param deliveryTag 消息投递标签(唯一标识)
* @throws Exception 异常
*/
@RabbitListener(queues = "${rabbitmq.queue.normal}")
public void consumeNormalMessage(Message message, Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws Exception {
try {
// 1. 获取消息ID和内容
String messageId = message.getMessageProperties().getMessageId();
String messageContent = new String(message.getBody(), "UTF-8");
System.out.println("收到普通队列消息,ID:" + messageId + ",内容:" + messageContent);
// 2. 使用 Jackson 解析消息(企业级:校验消息格式、幂等性)
RabbitMQProducerService.OrderMessage orderMessage =
objectMapper.readValue(messageContent, RabbitMQProducerService.OrderMessage.class);
// 3. 模拟业务处理(例如:更新订单状态、发送通知)
System.out.println("处理订单消息,订单ID:" + orderMessage.getOrderId() +
",订单名称:" + orderMessage.getOrderName());
// 4. 手动确认消息(ACK):消息处理成功,告知RabbitMQ删除消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功,已ACK,消息ID:" + messageId);
} catch (Exception e) {
System.err.println("消息处理失败,消息ID:" + message.getMessageProperties().getMessageId() +
",异常:" + e.getMessage());
// 企业级处理策略:
// 1. 重试次数未达上限:拒绝消息并重新入队(basicNack + requeue=true)
// 2. 重试次数已达上限:拒绝消息并进入死信队列(basicNack + requeue=false)
Integer retryCount = message.getMessageProperties().getHeader("x-retry-count");
if (retryCount == null) {
retryCount = 1;
} else {
retryCount++;
}
if (retryCount <= 3) {
// 重新入队,继续重试
channel.basicNack(deliveryTag, false, true);
System.out.println("消息重试中,当前重试次数:" + retryCount +
",消息ID:" + message.getMessageProperties().getMessageId());
} else {
// 拒绝入队,进入死信队列
channel.basicNack(deliveryTag, false, false);
System.out.println("消息重试次数已达上限,进入死信队列,消息ID:" +
message.getMessageProperties().getMessageId());
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# 5.2 死信消息消费者(处理失败消息)
在 cc.hep.consumer 包下创建 DeadLetterConsumer,处理死信队列的消息(企业级:记录失败消息,人工介入处理):
package cc.hep.consumer;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
/**
* 死信消息消费者(企业级:处理消费失败的消息)
*/
@Component
public class DeadLetterConsumer {
/**
* 消费死信队列消息
* @param message 消息体
* @param channel 通道
* @param deliveryTag 投递标签
* @throws Exception 异常
*/
@RabbitListener(queues = "${rabbitmq.queue.dead}")
public void consumeDeadLetterMessage(Message message, Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws Exception {
try {
// 1. 获取消息信息
String messageId = message.getMessageProperties().getMessageId();
String messageContent = new String(message.getBody(), "UTF-8");
System.err.println("收到死信队列消息,ID:" + messageId + ",内容:" + messageContent);
// 2. 企业级处理:记录死信消息到数据库/日志,通知运维人员人工介入
System.err.println("死信消息已记录,等待人工处理,消息ID:" + messageId);
// 3. 手动ACK(死信消息处理完成)
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
System.err.println("死信消息处理失败:" + e.getMessage());
// 死信消息处理失败,直接拒绝(避免无限循环)
channel.basicNack(deliveryTag, false, false);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 7. 项目启动与验证
# 7.1 启动项目
- 找到项目主类
SpringBootRabbitMqApplication(cc.hep 包下),右键点击Run。 - 控制台无报错,且显示
Started SpringBootRabbitMqApplication in xxx seconds,说明项目启动成功。
# 7.2 接口测试
- 发送普通订单消息:访问
http://localhost:8080/send/order?orderId=ORDER_001&orderName=苹果16 Pro,返回“普通订单消息发送成功”。 - 发送延迟订单消息:访问
http://localhost:8080/send/delay/order?orderId=ORDER_002&delayTime=5000,返回“延迟订单消息发送成功”。 - 查看控制台:能看到消费者打印的消息处理日志,验证消息发送和消费流程正常。
# 7.3 RabbitMQ 管理界面验证
- 访问
http://localhost:15672,登录后进入Queues页面。 - 查看
hep.normal.queue和hep.dead.queue的消息数量:- 普通消息发送后,
hep.normal.queue消息数先增加,消费后变为0。 - 延迟消息发送后,
hep.normal.queue消息数增加,延迟时间到后变为0,hep.dead.queue无消息(若处理正常)。
- 普通消息发送后,
# 8. 企业级生产环境注意事项
# 8.1 性能优化
- 连接池配置:根据业务量调整
spring.rabbitmq.cache.connection.size和spring.rabbitmq.cache.channel.size,避免连接耗尽。 - 消费并发数:根据服务器CPU核心数调整
spring.rabbitmq.listener.simple.concurrency和max-concurrency,建议CPU核心数*2。 - 预取数:
prefetch不宜过大(避免消费堆积),也不宜过小(降低消费效率),建议10-50。
# 8.2 可靠性保障
- 消息持久化:交换机、队列、消息均需设置持久化(代码中已配置
durable=true)。 - 发送确认:开启
confirmCallback和returnsCallback,确保消息到达交换机和队列。 - 手动ACK:消费端必须使用手动ACK,避免消息丢失。
- 死信队列:所有业务队列必须绑定死信队列,处理消费失败的消息。
# 8.3 监控与告警
- 集成 Prometheus + Grafana 监控 RabbitMQ 指标(消息堆积、消费速率、连接数等)。
- 配置告警规则:消息堆积超过阈值、消费失败次数过多时,及时告警给运维人员。
# 8.4 幂等性保障
- 基于消息ID + Redis 实现幂等:消费前先检查Redis中是否有该消息ID,有则跳过,无则处理并记录。
- 业务层幂等:例如订单消息处理时,先检查订单状态,避免重复处理。
# 总结
# 核心要点回顾
- 项目搭建:基于 IDEA 初始化 SpringBoot 项目,引入 RabbitMQ 核心依赖,配置文件对齐企业级规范(连接池、手动ACK、重试机制)。
- 核心配置:通过配置类声明交换机、队列、绑定关系,配置 RabbitTemplate 实现消息发送确认和JSON序列化。
- 生产者:封装通用发送工具类,业务层结合实际场景发送普通/延迟消息,控制器提供HTTP接口。
- 消费者:手动ACK处理消息,异常时根据重试次数决定重新入队或进入死信队列,死信队列消费失败消息供人工处理。
- 企业级保障:消息持久化、发送确认、手动ACK、死信队列是保障RabbitMQ可靠性的核心,生产环境需重点关注。
# 扩展方向
- 集成 RocketMQ/ Kafka:若业务量极大,可替换为更高吞吐量的消息中间件。
- 消息追踪:开启 RabbitMQ 的
rabbitmq_tracing插件,追踪消息全链路。 - 分布式事务:结合 RabbitMQ 实现最终一致性分布式事务(Seata + RabbitMQ)。