一、Maven 依赖
xml
<!-- RabbitMQ 核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- 可选:JSON 序列化 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
二、基础配置(application.yml)
yaml
spring:
rabbitmq:
# ==================== 连接配置 ====================
host: localhost # RabbitMQ 服务器地址
port: 5672 # 端口,默认5672
username: guest # 用户名,默认guest
password: guest # 密码,默认guest
virtual-host: / # 虚拟主机,默认/
# ==================== 连接池配置 ====================
# 使用连接池(需要引入spring-boot-starter-amqp依赖)
connection:
name: rabbitmq-connection # 连接名称
factory:
cache-mode: CHANNEL # 连接缓存模式:CHANNEL(默认)或CONNECTION
channel-cache-size: 25 # 每个连接缓存的通道数
channel-checkout-timeout: 10000 # 获取通道超时时间(ms)
# ==================== 连接重试配置 ====================
connection-timeout: 60000 # 连接超时时间(ms)
requested-heartbeat: 60 # 心跳超时时间(秒)
# 自动重连配置
retry:
enabled: true # 开启重试机制
max-attempts: 3 # 最大重试次数
initial-interval: 1000 # 初始重试间隔(ms)
multiplier: 1.0 # 重试间隔乘数
max-interval: 10000 # 最大重试间隔(ms)
# ==================== 消息确认配置 ====================
publisher-confirms: true # 已废弃,使用publisher-confirm-type
publisher-confirm-type: correlated # 发布者确认模式
# 可选值:
# none: 禁用
# simple: 同步确认(性能差)
# correlated: 异步确认(推荐)
publisher-returns: true # 开启发布者返回模式
template:
mandatory: true # 强制消息路由
# ==================== 消费者配置 ====================
listener:
simple:
acknowledge-mode: manual # 确认模式:AUTO(自动), MANUAL(手动), NONE(不确认)
prefetch: 10 # 每个消费者最大预取消息数
concurrency: 5 # 最小并发消费者数
max-concurrency: 10 # 最大并发消费者数
retry:
enabled: true # 开启消费者重试
max-attempts: 3 # 最大重试次数
initial-interval: 1000 # 重试间隔
max-interval: 10000 # 最大重试间隔
multiplier: 1.0 # 间隔乘数
stateless: true # 是否为无状态重试
# 消费者异常处理
default-requeue-rejected: false # 是否重新入队被拒绝的消息
missing-queues-fatal: false # 队列不存在是否致命
idle-event-interval: 60000 # 空闲事件间隔(ms)
三、高级配置类(Java Config)
java
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
public class RabbitMQConfig {
// ==================== 队列、交换机、路由键定义 ====================
public static final String DIRECT_EXCHANGE = "direct.exchange";
public static final String TOPIC_EXCHANGE = "topic.exchange";
public static final String FANOUT_EXCHANGE = "fanout.exchange";
public static final String DELAYED_EXCHANGE = "delayed.exchange";
public static final String ORDER_QUEUE = "order.queue";
public static final String PAYMENT_QUEUE = "payment.queue";
public static final String DEAD_LETTER_QUEUE = "dead.letter.queue";
public static final String DELAY_QUEUE = "delay.queue";
public static final String ORDER_ROUTING_KEY = "order.routing.key";
public static final String PAYMENT_ROUTING_KEY = "payment.routing.key";
// ==================== 消息转换器 ====================
@Bean
public MessageConverter jsonMessageConverter(ObjectMapper objectMapper) {
// 使用JSON序列化
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
converter.setObjectMapper(objectMapper);
return converter;
}
// ==================== RabbitTemplate配置 ====================
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory,
MessageConverter messageConverter) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter);
// 消息发送确认回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
System.out.println("消息发送成功: " + correlationData);
} else {
System.out.println("消息发送失败: " + cause);
}
});
// 消息返回回调(路由失败时触发)
rabbitTemplate.setReturnsCallback(returned -> {
System.out.println("消息被退回: " + returned.getMessage());
System.out.println("退回码: " + returned.getReplyCode());
System.out.println("退回原因: " + returned.getReplyText());
System.out.println("交换机: " + returned.getExchange());
System.out.println("路由键: " + returned.getRoutingKey());
});
// 设置强制路由
rabbitTemplate.setMandatory(true);
return rabbitTemplate;
}
// ==================== RabbitAdmin配置 ====================
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
admin.setAutoStartup(true); // 自动声明队列和交换机
return admin;
}
// ==================== 监听器容器工厂配置 ====================
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory,
MessageConverter messageConverter) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(messageConverter);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL); // 手动确认
factory.setPrefetchCount(10); // 预取数量
factory.setConcurrentConsumers(5); // 并发消费者
factory.setMaxConcurrentConsumers(10); // 最大并发消费者
// 设置消费者异常处理器
factory.setErrorHandler(t -> {
System.err.println("消费消息异常: " + t.getMessage());
});
// 设置消息监听器异常处理器
factory.setDefaultRequeueRejected(false); // 不重新入队
return factory;
}
// ==================== 声明队列 ====================
@Bean
public Queue orderQueue() {
// 普通队列
return QueueBuilder.durable(ORDER_QUEUE) // 持久化
.withArgument("x-queue-type", "classic") // 队列类型
.build();
}
@Bean
public Queue paymentQueue() {
// 带死信队列的配置
return QueueBuilder.durable(PAYMENT_QUEUE)
.withArgument("x-dead-letter-exchange", "") // 死信交换机
.withArgument("x-dead-letter-routing-key", DEAD_LETTER_QUEUE) // 死信路由键
.withArgument("x-message-ttl", 60000) // 消息TTL(ms)
.withArgument("x-max-length", 1000) // 队列最大长度
.withArgument("x-overflow", "reject-publish") // 溢出策略
.build();
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder.durable(DEAD_LETTER_QUEUE).build();
}
@Bean
public Queue delayQueue() {
// 延迟队列(需要插件rabbitmq_delayed_message_exchange)
return QueueBuilder.durable(DELAY_QUEUE).build();
}
// ==================== 声明交换机 ====================
@Bean
public DirectExchange directExchange() {
return ExchangeBuilder.directExchange(DIRECT_EXCHANGE)
.durable(true) // 持久化
.build();
}
@Bean
public TopicExchange topicExchange() {
return ExchangeBuilder.topicExchange(TOPIC_EXCHANGE)
.durable(true)
.build();
}
@Bean
public FanoutExchange fanoutExchange() {
return ExchangeBuilder.fanoutExchange(FANOUT_EXCHANGE)
.durable(true)
.build();
}
@Bean
public CustomExchange delayedExchange() {
// 延迟交换机(需要插件支持)
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
return new CustomExchange(DELAYED_EXCHANGE, "x-delayed-message", true, false, args);
}
// ==================== 绑定队列和交换机 ====================
@Bean
public Binding orderBinding() {
return BindingBuilder.bind(orderQueue())
.to(directExchange())
.with(ORDER_ROUTING_KEY);
}
@Bean
public Binding paymentBinding() {
return BindingBuilder.bind(paymentQueue())
.to(topicExchange())
.with(PAYMENT_ROUTING_KEY);
}
@Bean
public Binding delayBinding() {
return BindingBuilder.bind(delayQueue())
.to(delayedExchange())
.with("delay.routing.key")
.noargs();
}
}
四、生产者配置
java
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.MessageDeliveryMode;
import java.util.UUID;
@Component
public class RabbitMQProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送普通消息
*/
public void sendMessage(String exchange, String routingKey, Object message) {
// 设置消息ID
String messageId = UUID.randomUUID().toString();
rabbitTemplate.convertAndSend(exchange, routingKey, message, m -> {
// 设置消息属性
m.getMessageProperties().setMessageId(messageId);
m.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT); // 持久化
m.getMessageProperties().setPriority(1); // 优先级
m.getMessageProperties().setContentEncoding("UTF-8");
m.getMessageProperties().setContentType("application/json");
return m;
});
}
/**
* 发送延迟消息(需要插件支持)
*/
public void sendDelayedMessage(String exchange, String routingKey,
Object message, int delayMillis) {
rabbitTemplate.convertAndSend(exchange, routingKey, message, m -> {
m.getMessageProperties().setDelay(delayMillis);
return m;
});
}
/**
* 发送确认消息(使用CorrelationData)
*/
public void sendConfirmMessage(String exchange, String routingKey,
Object message) {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
correlationData.getFuture().addCallback(
result -> {
if (result.isAck()) {
System.out.println("消息确认成功: " + correlationData.getId());
} else {
System.out.println("消息确认失败: " + correlationData.getId());
}
},
ex -> {
System.out.println("发送异常: " + ex.getMessage());
}
);
rabbitTemplate.convertAndSend(exchange, routingKey, message, correlationData);
}
}
五、消费者配置
java
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
import java.io.IOException;
@Component
public class RabbitMQConsumer {
/**
* 使用注解监听队列
* @RabbitListener: 声明监听器
* @QueueBinding: 绑定队列和交换机
*/
@RabbitListener(
bindings = @QueueBinding(
value = @Queue(value = "order.queue", durable = "true"),
exchange = @Exchange(value = "direct.exchange", type = ExchangeTypes.DIRECT),
key = "order.routing.key"
),
concurrency = "5-10" // 并发配置
)
public void handleOrderMessage(Order order,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 业务处理逻辑
System.out.println("收到订单消息: " + order);
// 手动确认消息
channel.basicAck(deliveryTag, false);
// 拒绝消息(重新入队)
// channel.basicReject(deliveryTag, true);
// 拒绝消息(不重新入队)
// channel.basicReject(deliveryTag, false);
// 批量确认
// channel.basicAck(deliveryTag, true);
} catch (Exception e) {
// 处理失败,重新入队
channel.basicReject(deliveryTag, true);
// 或放入死信队列
// channel.basicReject(deliveryTag, false);
}
}
/**
* 死信队列消费者
*/
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetterMessage(Message message, Channel channel) throws IOException {
System.out.println("收到死信消息: " + new String(message.getBody()));
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
/**
* 延迟队列消费者
*/
@RabbitListener(queues = "delay.queue")
public void handleDelayMessage(Message message, Channel channel) throws IOException {
System.out.println("收到延迟消息: " + new String(message.getBody()));
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
// 消息实体类
class Order {
private String orderId;
private String productName;
private Double amount;
// getter/setter省略
}
六、事务配置
java
import org.springframework.amqp.rabbit.transaction.RabbitTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
/**
* RabbitMQ 事务管理器
*/
@Bean
public RabbitTransactionManager rabbitTransactionManager(
ConnectionFactory connectionFactory) {
return new RabbitTransactionManager(connectionFactory);
}
}
// 使用事务
@Component
class TransactionalService {
@Autowired
private RabbitTemplate rabbitTemplate;
@Transactional
public void processWithTransaction(Order order) {
// 1. 保存到数据库
// orderRepository.save(order);
// 2. 发送消息(如果在事务中,会在事务提交后发送)
rabbitTemplate.convertAndSend("exchange", "routingKey", order);
// 如果发生异常,消息不会被发送
// throw new RuntimeException("模拟异常");
}
}
七、监控和健康检查配置
java
management:
endpoints:
web:
exposure:
include: health,metrics,rabbitmq
endpoint:
health:
show-details: always
spring:
rabbitmq:
# 启用健康检查
metrics:
enabled: true
# 收集消息统计
collect-message-history: true
八、常见配置问题解决方案
- 连接断开重连
yaml
spring:
rabbitmq:
connection-timeout: 60000
requested-heartbeat: 60
retry:
enabled: true
max-attempts: 3
- 消费者堆积处理
java
@Bean
public SimpleRabbitListenerContainerFactory containerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPrefetchCount(100); // 增大预取值
factory.setConcurrentConsumers(20); // 增加并发消费者
factory.setMaxConcurrentConsumers(50);
return factory;
}
- 消息序列化配置
java
@Bean
public MessageConverter messageConverter() {
// 设置全局消息转换器
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
DefaultJackson2JavaTypeMapper typeMapper = new DefaultJackson2JavaTypeMapper();
typeMapper.setTrustedPackages("com.example.entity.*");
converter.setJavaTypeMapper(typeMapper);
return converter;
}
九、最佳实践总结
生产环境必须配置:
- 持久化队列和消息
- 手动确认模式
- 死信队列处理
- 合理的重试机制
性能优化:
- 适当调整预取值(prefetch)
- 合理设置并发消费者数
- 使用连接池
- 批量确认消息
高可用:
- 配置集群连接
- 启用镜像队列
- 设置合理的TTL和死信队列
监控:
- 开启RabbitMQ管理插件
- 集成Spring Boot Actuator
- 配置告警机制