目录
-
-
2.1 Maven 依赖
-
2.2 Gradle 依赖
-
2.3 Spring Boot 自动配置
-
2.4 纯 Java 配置
-
2.5 XML 配置
-
1. Spring AMQP 概述
Spring AMQP 是一个基于 AMQP(Advanced Message Queuing Protocol) 协议的消息中间件框架,提供简洁的 API 来发送和接收异步、可靠的消息。它是 Spring 生态的一部分,与 Spring Boot、Spring Integration 等项目无缝集成。
核心能力:
-
AmqpTemplate / RabbitTemplate:高层抽象,简化消息的发送与接收
-
@RabbitListener:注解驱动的消息驱动 POJO
-
消息转换器:自动进行 Java 对象与 AMQP 消息体之间的序列化/反序列化
-
连接管理:连接与 Channel 的缓存、自动恢复
-
声明式配置:Exchange、Queue、Binding 的自动声明
-
消息确认、事务、重试:可靠性保障机制
-
Micrometer 可观测性:指标与链路追踪
版本兼容性(3.0.x):
-
Java 17+
-
Spring Framework 6.0+
-
RabbitMQ amqp-client 5.7.0+
2. 快速集成
2.1 Maven 依赖
<dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>3.0.4</version> </dependency>
2.2 Gradle 依赖
implementation 'org.springframework.amqp:spring-rabbit:3.0.4'
2.3 Spring Boot 自动配置(推荐)
Spring Boot 自动配置 ConnectionFactory、RabbitTemplate、RabbitAdmin 等基础设施 Bean。
application.yml:
spring: rabbitmq: host: localhost port: 5672 username: guest password: guest virtual-host: / # 发布者确认 publisher-confirm-type: correlated publisher-returns: true # 消费者 listener: simple: concurrency: 3 max-concurrency: 10 acknowledge-mode: manual retry: enabled: true max-attempts: 3 initial-interval: 1000ms
示例应用:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Queue myQueue() {
return new Queue("myqueue");
}
@Bean
public ApplicationRunner runner(RabbitTemplate template) {
return args -> template.convertAndSend("myqueue", "Hello, World!");
}
@RabbitListener(queues = "myqueue")
public void listen(String message) {
System.out.println("Received: " + message);
}
}
2.4 纯 Java 配置
@Configuration
public class RabbitConfiguration {
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
// 启用发布者确认
factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
factory.setPublisherReturns(true);
return factory;
}
@Bean
public RabbitAdmin amqpAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
// 设置消息转换器
template.setMessageConverter(jackson2MessageConverter());
// 确认回调
template.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
System.out.println("消息发送成功: " + correlationData);
} else {
System.err.println("消息发送失败: " + cause);
}
});
// 返回回调
template.setReturnsCallback(returned -> {
System.err.println("消息被退回: " + returned.getMessage());
});
return template;
}
@Bean
public Jackson2JsonMessageConverter jackson2MessageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public Queue myQueue() {
return new Queue("myqueue", true); // 持久化队列
}
}
2.5 XML 配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation=" http://www.springframework.org/schema/rabbit https://www.springframework.org/schema/rabbit/spring-rabbit.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <rabbit:connection-factory id="connectionFactory" host="localhost"/> <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"/> <rabbit:admin connection-factory="connectionFactory"/> <rabbit:queue name="myqueue"/> </beans>
3. 核心概念
3.1 AMQP 抽象
AMQP 协议的三大核心要素:
| 概念 | 说明 | 关键类 |
|---|---|---|
| Exchange | 消息交换机,接收生产者消息并按路由规则分发到队列 | DirectExchange, TopicExchange, FanoutExchange, HeadersExchange |
| Queue | 消息队列,存储消息直到被消费者取走 | Queue, AnonymousQueue |
| Binding | 绑定关系,定义 Exchange 到 Queue 的路由规则(routing key) | Binding |
| Message | 消息体,包含 body(字节数组)和 properties(消息属性) | Message |
Exchange 类型:
// Direct Exchange:精确匹配 routing key
new DirectExchange("order.exchange");
// Topic Exchange:通配符匹配 routing key(* 匹配一个词,# 匹配零个或多个词)
new TopicExchange("event.exchange");
// Fanout Exchange:广播到所有绑定队列,忽略 routing key
new FanoutExchange("broadcast.exchange");
// Headers Exchange:根据消息 headers 匹配
new HeadersExchange("header.exchange");
声明示例:
@Bean
public DirectExchange orderExchange() {
return new DirectExchange("order.exchange", true, false);
}
@Bean
public Queue orderQueue() {
return QueueBuilder.durable("order.queue")
.withArgument("x-dead-letter-exchange", "dlx.exchange")
.withArgument("x-dead-letter-routing-key", "dlx.routing.key")
.build();
}
@Bean
public Binding orderBinding(DirectExchange orderExchange, Queue orderQueue) {
return BindingBuilder.bind(orderQueue)
.to(orderExchange)
.with("order.created");
}
3.2 连接与资源管理
CachingConnectionFactory(核心连接工厂)
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
factory.setPort(5672);
// Channel 缓存大小(默认 25)
factory.setChannelCacheSize(50);
// 连接缓存模式:CHANNEL(默认)/ CONNECTION
factory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL);
// 连接限制
factory.setChannelCheckoutTimeout(1000); // Channel 获取超时(ms)
// 发布者确认
factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
factory.setPublisherReturns(true);
return factory;
}
SSL 配置
@Bean
public RabbitConnectionFactoryBean rabbitConnectionFactory() {
RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();
factory.setUseSSL(true);
factory.setSslAlgorithm("TLSv1.2");
factory.setKeyStore("file:/path/to/keystore.jks");
factory.setKeyStorePassphrase("password");
factory.setTrustStore("file:/path/to/truststore.jks");
factory.setTrustStorePassphrase("password");
return factory;
}
@Bean
public CachingConnectionFactory connectionFactory(
RabbitConnectionFactoryBean rabbitConnectionFactory) throws Exception {
return new CachingConnectionFactory(rabbitConnectionFactory.getObject());
}
集群连接
// addresses 格式:host1:port1,host2:port2
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setAddresses("rabbit1:5672,rabbit2:5672,rabbit3:5672");
factory.setUsername("guest");
factory.setPassword("guest");
return factory;
}
// 使用 AddressResolver 动态发现
@Bean
public CachingConnectionFactory connectionFactory(AddressResolver addressResolver) {
CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setAddressResolver(addressResolver);
return factory;
}
RabbitMQ 自动连接/拓扑恢复
spring: rabbitmq: connection-timeout: 30000 requested-heartbeat: 60s # 自动恢复(RabbitMQ 客户端 4.0+ 默认启用) # 以下参数可覆写默认恢复行为
3.3 AmqpTemplate / RabbitTemplate
RabbitTemplate 是 AmqpTemplate 接口的核心实现,提供同步和异步消息操作。
添加重试能力
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
// 配置重试模板
RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(3)
.fixedBackoff(1000) // 固定间隔 1s
.retryOn(AmqpIOException.class)
.build();
template.setRetryTemplate(retryTemplate);
return template;
}
异步发布 — 检测成功与失败
// 确认回调
template.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息 {} 已确认", correlationData.getId());
} else {
log.error("消息 {} 发送失败: {}", correlationData.getId(), cause);
// 可在此做补偿逻辑:重发、记录到数据库
}
});
// 退回回调(消息无法路由到队列时触发)
template.setReturnsCallback(returned -> {
Message message = returned.getMessage();
String replyText = returned.getReplyText();
String exchange = returned.getExchange();
String routingKey = returned.getRoutingKey();
log.error("消息被退回: replyText={}, exchange={}, routingKey={}",
replyText, exchange, routingKey);
});
Scope 操作(声明式交换/队列绑定后发送)
// 使用 invoke 方法,在发送消息前确保交换和队列已声明
template.invoke(t -> {
// 在此声明
t.execute(channel -> {
channel.exchangeDeclare("temp.exchange", "direct", true);
channel.queueDeclare("temp.queue", true, false, false, null);
channel.queueBind("temp.queue", "temp.exchange", "routing.key");
return null;
});
// 然后发送
t.convertAndSend("temp.exchange", "routing.key", payload);
return null;
});
4. 消息发送
Message Builder API
// 方式一:MessageBuilder
Message message = MessageBuilder.withBody("Hello".getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)
.setMessageId(UUID.randomUUID().toString())
.setHeader("custom-header", "custom-value")
.setPriority(5)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.build();
template.send("my.exchange", "my.routing.key", message);
// 方式二:MessagePostProcessor
template.convertAndSend("my.exchange", "my.routing.key", payload, msg -> {
msg.getMessageProperties().setHeader("trace-id", traceId());
msg.getMessageProperties().setExpiration("60000"); // 60s TTL
return msg;
});
批处理
// 发送批量消息
List<Message> messages = Arrays.asList(
MessageBuilder.withBody("batch-1".getBytes()).build(),
MessageBuilder.withBody("batch-2".getBytes()).build(),
MessageBuilder.withBody("batch-3".getBytes()).build()
);
// BatchingStrategy 控制批次大小和缓冲时间
BatchingRabbitTemplate batchingTemplate = new BatchingRabbitTemplate(
connectionFactory,
new SimpleBatchingStrategy(100, 1024 * 1024, 5000) // 100条/1MB/5s
);
batchingTemplate.send("my.exchange", "my.routing.key", messages);
5. 消息接收
消费者轮询(Polling Consumer)
// 同步接收
Message msg = template.receive("my.queue", 3000); // 3s 超时
String body = (String) template.receiveAndConvert("my.queue", 3000);
// 支持超时和类型转换
Order order = (Order) template.receiveAndConvert("order.queue", 5000);
异步消费者 — @RabbitListener
@Component
public class OrderListener {
@RabbitListener(queues = "order.queue")
public void handleOrder(Order order) {
log.info("收到订单: {}", order);
processOrder(order);
}
// 手动确认模式
@RabbitListener(queues = "order.queue", ackMode = "MANUAL")
public void handleOrderManual(Order order, Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long tag) {
try {
processOrder(order);
channel.basicAck(tag, false);
} catch (Exception e) {
channel.basicNack(tag, false, true); // requeue
}
}
// 监听多个队列
@RabbitListener(queues = {"order.created", "order.updated", "order.cancelled"})
public void handleOrderEvents(OrderEvent event,
@Header("event-type") String eventType) {
log.info("事件 [{}]: {}", eventType, event);
}
// 批处理监听
@RabbitListener(queues = "order.batch.queue", containerFactory = "batchContainerFactory")
public void handleBatch(List<Order> orders) {
log.info("批量处理 {} 条订单", orders.size());
orders.forEach(this::processOrder);
}
// 异步返回
@RabbitListener(queues = "rpc.queue")
@SendTo("reply.queue") // 将返回值发送到 reply.queue
public String handleRpc(String request) {
return "Response for: " + request;
}
}
容器工厂配置
@Configuration
public class ListenerConfig {
// 常规容器工厂
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setConcurrentConsumers(3); // 初始并发消费者
factory.setMaxConcurrentConsumers(10); // 最大并发消费者
factory.setPrefetchCount(50); // 预取数量
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setDefaultRequeueRejected(false); // 拒绝时不重新入队
factory.setMessageConverter(jackson2MessageConverter());
return factory;
}
// 批处理容器工厂
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setBatchListener(true); // 启用批处理
factory.setBatchSize(50); // 批次大小
factory.setConsumerBatchEnabled(true); // 消费者端批次
factory.setReceiveTimeout(5000L); // 批次超时
return factory;
}
@Bean
public Jackson2JsonMessageConverter jackson2MessageConverter() {
return new Jackson2JsonMessageConverter();
}
}
两种容器对比
| 特性 | SimpleMessageListenerContainer | DirectMessageListenerContainer |
|---|---|---|
| 并发模型 | 多线程,每个消费者一个线程 | 每个队列一个 Channel,单线程 |
| 适用场景 | 事务、大量队列、需严格排序 | 高吞吐、少量队列、低延迟 |
| 预取控制 | 支持 prefetchCount | 支持 prefetchCount |
| 事务支持 | ✅ | ❌ |
| 动态扩缩 | ✅ | ❌ |
| 使用方式 | 默认容器 | 需显式指定 containerFactory |
6. 消息转换器
常用转换器一览
// 1. SimpleMessageConverter — 默认,处理 String、byte[]、Serializable
template.setMessageConverter(new SimpleMessageConverter());
// 2. Jackson2JsonMessageConverter — JSON 序列化(推荐)
Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter();
// 支持类型安全反序列化
jsonConverter.setClassMapper(new DefaultJackson2JavaTypeMapper());
template.setMessageConverter(jsonConverter);
// 3. Jackson2XmlMessageConverter — XML 序列化
template.setMessageConverter(new Jackson2XmlMessageConverter());
// 4. MarshallingMessageConverter — 基于 Spring OXM
template.setMessageConverter(new MarshallingMessageConverter(jaxb2Marshaller()));
// 5. ContentTypeDelegatingMessageConverter — 根据 Content-Type 委托
ContentTypeDelegatingMessageConverter delegating = new ContentTypeDelegatingMessageConverter();
delegating.addDelegate("application/json", jsonConverter);
delegating.addDelegate("application/xml", xmlConverter);
delegating.addDelegate("text/plain", simpleConverter);
template.setMessageConverter(delegating);
类型安全的 JSON 转换
@RabbitListener(queues = "order.queue")
public void handleOrder(
@Payload Order order,
@Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey) {
// @Payload 配合 DefaultJackson2JavaTypeMapper 确保类型正确
}
// 自定义 ClassMapper:通过消息头指定类型
DefaultJackson2JavaTypeMapper typeMapper = new DefaultJackson2JavaTypeMapper();
typeMapper.setTypePrecedence(Jackson2JavaTypeMapper.TypePrecedence.TYPE_ID);
// 消息发送时自动设置 __TypeId__ header
消息属性转换器
// 自定义 MessagePropertiesConverter // 可自定义 AMQP 消息属性与 Spring MessageProperties 的映射
7. 请求 / 回复模式
同步请求 / 回复
// 发送并等待回复 Object response = template.convertSendAndReceive( "rpc.exchange", "rpc.key", request); // 默认超时 5s,可配置 template.setReplyTimeout(30000);
异步请求 / 回复 — AsyncRabbitTemplate
@Configuration
public class AsyncConfig {
@Bean
public AsyncRabbitTemplate asyncRabbitTemplate(
ConnectionFactory connectionFactory) {
// 方式一:使用固定回复队列
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
Queue replyQueue = new Queue("async.reply.queue");
AsyncRabbitTemplate asyncTemplate = new AsyncRabbitTemplate(
rabbitTemplate, new SimpleMessageListenerContainer(connectionFactory), replyQueue.getName());
return asyncTemplate;
}
}
// 使用
@Component
public class RpcClient {
@Autowired
private AsyncRabbitTemplate asyncTemplate;
public CompletableFuture<String> callAsync(String request) {
RabbitConverterFuture<String> future = asyncTemplate.convertSendAndReceiveAsType(
"rpc.exchange", "rpc.key", request,
new ParameterizedTypeReference<String>() {});
return future.completable(); // 转换为 CompletableFuture
}
}
服务端 — @RabbitListener + @SendTo
@RabbitListener(queues = "rpc.queue")
@SendTo("reply.to.queue") // 自动将返回值发送到指定队列
public OrderResult processOrder(OrderRequest request) {
return orderService.process(request);
}
RabbitMQ Direct Reply-to(零队列优化)
// 启用 Direct Reply-to,无需声明回复队列,性能更优
template.setUseDirectReplyToContainer(true);
template.setReplyAddress("amq.rabbitmq.reply-to"); // 伪队列名
8. Broker 配置
Builder API 声明
@Configuration
public class BrokerConfig {
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
admin.setAutoStartup(true); // 自动声明
return admin;
}
// Exchange Builder
@Bean
public DirectExchange orderExchange() {
return ExchangeBuilder.directExchange("order.exchange")
.durable(true)
.autoDelete(false)
.delayed()
.build();
}
// Queue Builder(带死信配置)
@Bean
public Queue orderQueue() {
return QueueBuilder.durable("order.queue")
.withArgument("x-dead-letter-exchange", "dlx.exchange")
.withArgument("x-dead-letter-routing-key", "order.dead")
.withArgument("x-message-ttl", 60000) // 消息 TTL
.withArgument("x-max-length", 10000) // 最大长度
.maxPriority(10) // 最大优先级
.quorum() // 仲裁队列
.build();
}
// Binding Builder
@Bean
public Binding orderBinding() {
return BindingBuilder.bind(orderQueue())
.to(orderExchange())
.with("order.created");
}
// 延迟队列插件(需要安装 rabbitmq_delayed_message_exchange)
@Bean
public DirectExchange delayedExchange() {
return ExchangeBuilder.directExchange("delayed.exchange")
.delayed()
.build();
}
// 发送延迟消息
public void sendDelayed(Object payload, int delayMs) {
template.convertAndSend("delayed.exchange", "delayed.key", payload, msg -> {
msg.getMessageProperties().setDelay(delayMs);
return msg;
});
}
// AnonymousQueue(自动生成名称,连接断开自动删除)
@Bean
public Queue anonymousQueue() {
return new AnonymousQueue();
}
// 条件声明
@Bean
public Declarables declarables() {
return new Declarables(
new DirectExchange("conditional.exchange"),
new Queue("conditional.queue"),
new Binding("conditional.queue", Binding.DestinationType.QUEUE,
"conditional.exchange", "routing.key", null)
);
}
}
Broker 事件监听器
@Component
public class BrokerEventListener implements ApplicationListener<BrokerEvent> {
@Override
public void onApplicationEvent(BrokerEvent event) {
if (event instanceof BrokerAvailableEvent) {
log.info("Broker 已可用");
} else if (event instanceof BrokerUnavailableEvent) {
log.warn("Broker 不可用");
}
}
// 或通过 @EventListener
@EventListener
public void handleBrokerAvailable(BrokerAvailableEvent event) {
log.info("Broker 可用");
}
}
9. 异常处理与重试
重试策略配置
// 监听器级别重试
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 使用 RetryTemplate
RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(3)
.exponentialBackoff(1000, 2.0, 10000) // 指数退避
.retryOn(AmqpRejectAndDontRequeueException.class) // 不重试的异常
.build();
factory.setRetryTemplate(retryTemplate);
return factory;
}
死信队列与 RepublishMessageRecoverer
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 重试耗尽后将消息重新发布到死信队列
MessageRecoverer recoverer = new RepublishMessageRecoverer(
rabbitTemplate(connectionFactory), "dlx.exchange", "dlx.routing.key");
RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(3)
.exponentialBackoff(1000, 2.0, 10000)
.build();
factory.setRetryTemplate(retryTemplate);
factory.setRecoveryCallback(new RetryContextExhaustedMessageRecoverer(recoverer));
return factory;
}
@RabbitListener 异常处理
@Component
public class ExceptionHandlingListener {
@RabbitListener(queues = "order.queue")
public void handleOrder(Order order) {
try {
processOrder(order);
} catch (OrderValidationException e) {
// 业务异常,不重试,直接拒绝
throw new AmqpRejectAndDontRequeueException("订单校验失败", e);
} catch (TemporaryException e) {
// 临时异常,重试
throw e;
}
}
// 全局异常处理器
@RabbitListener(queues = "order.queue", errorHandler = "myErrorHandler")
public void handleWithErrorHandler(Order order) {
processOrder(order);
}
}
// 自定义 ErrorHandler
@Component("myErrorHandler")
public class CustomErrorHandler implements RabbitListenerErrorHandler {
@Override
public Object handleError(Message amqpMessage, org.springframework.messaging.Message<?> message,
ListenerExecutionFailedException exception) {
log.error("消息处理失败: {}", new String(amqpMessage.getBody()), exception);
// 返回 null 表示消费成功(丢弃消息)
return null;
}
}
10. 事务支持
// 1. 启用 RabbitTemplate 事务
template.setChannelTransacted(true);
// 2. 使用 RabbitTransactionManager
@Bean
public RabbitTransactionManager transactionManager(
ConnectionFactory connectionFactory) {
return new RabbitTransactionManager(connectionFactory);
}
// 3. @Transactional 声明式事务
@Transactional(transactionManager = "rabbitTransactionManager")
public void sendWithTransaction() {
template.convertAndSend("exchange", "queue1", "message1");
template.convertAndSend("exchange", "queue2", "message2");
// 如果任一发送失败,两者都回滚
}
// 4. 监听器容器事务
@Bean
public SimpleRabbitListenerContainerFactory transactionalContainerFactory(
ConnectionFactory connectionFactory,
RabbitTransactionManager transactionManager) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setChannelTransacted(true);
factory.setTransactionManager(transactionManager);
return factory;
}
// 5. 条件回滚
@Transactional(transactionManager = "rabbitTransactionManager")
public void conditionalRollback() {
template.convertAndSend("exchange", "queueA", "msgA");
// 基于条件决定是否回滚
if (shouldRollback()) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
11. 监听器容器配置
SimpleMessageListenerContainer 直接编程式
@Bean
public SimpleMessageListenerContainer messageListenerContainer(
ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames("order.queue", "event.queue");
container.setMessageListener(listenerAdapter);
container.setConcurrentConsumers(5);
container.setMaxConcurrentConsumers(20);
container.setPrefetchCount(100);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setAutoStartup(true);
return container;
}
// MessageListenerAdapter 适配 POJO
@Bean
public MessageListenerAdapter listenerAdapter(OrderProcessor processor) {
MessageListenerAdapter adapter = new MessageListenerAdapter(processor);
adapter.setDefaultListenerMethod("process");
adapter.setMessageConverter(jackson2MessageConverter());
return adapter;
}
DirectMessageListenerContainer
@Bean
public DirectRabbitListenerContainerFactory directContainerFactory(
ConnectionFactory connectionFactory) {
DirectRabbitListenerContainerFactory factory = new DirectRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setConsumersPerQueue(5); // 每个队列的消费者数
factory.setPrefetchCount(100);
return factory;
}
// 使用时指定
@RabbitListener(queues = "high.throughput.queue",
containerFactory = "directContainerFactory")
public void handleHighThroughput(Message msg) {
// 高吞吐场景
}
12. 容错与恢复(Resilience)
自动恢复机制
Spring AMQP 内置了从 Broker 故障中恢复的能力:
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
// 连接恢复间隔
factory.setRecoveryInterval(5000);
return factory;
}
RabbitAdmin 自动声明
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
// Broker 恢复连接后自动重新声明 Exchange/Queue/Binding
admin.setAutoStartup(true);
return admin;
}
同步操作失败重试
// RabbitTemplate 层面自动重试
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(5)
.exponentialBackoff(500, 2.0, 5000)
.retryOn(AmqpConnectException.class)
.build();
template.setRetryTemplate(retryTemplate);
return template;
}
异常分类
// 致命异常 — 不应重试 AmqpRejectAndDontRequeueException // 拒绝且不重新入队 ImmediateAcknowledgeAmqpException // 立即确认(丢弃) MessageConversionException // 消息转换失败 // 可重试异常 — 建议重试 AmqpConnectException // 连接异常 AmqpIOException // IO 异常 ListenerExecutionFailedException // 监听器执行失败
13. 测试支持
@SpringRabbitTest
@SpringRabbitTest
@SpringBootTest
class OrderListenerTest {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RabbitListenerTestHarness harness;
@Test
void testOrderProcessing() throws InterruptedException {
// 发送测试消息
rabbitTemplate.convertAndSend("order.exchange", "order.created",
new Order("test-order", 100));
// 获取监听器 spy
OrderListener listener = harness.getSpy("orderListener");
// 验证
verify(listener, timeout(5000)).handleOrder(any(Order.class));
}
}
@RabbitListenerTest 与 RabbitListenerTestHarness
@SpringBootTest
class ListenerTest {
@Autowired
private RabbitListenerTestHarness harness;
@Test
void testCapture() {
RabbitListenerTestHarness.InvocationData invocationData =
harness.getNextInvocationDataFor("myListener", 10, TimeUnit.SECONDS);
assertNotNull(invocationData);
assertEquals("expected-payload", invocationData.getArguments()[0]);
}
}
TestRabbitTemplate
@Test
void testWithTestTemplate() {
TestRabbitTemplate template = new TestRabbitTemplate(connectionFactory);
template.convertAndSend("order.exchange", "order.created", testOrder);
// 等待处理并通过模板验证状态
}
JUnit5 条件
@RabbitAvailable // Broker 可用时才执行
@SpringBootTest
class IntegrationTest {
@Test
void testWithBroker() {
// 仅在 RabbitMQ 可用时运行
}
}
@LongRunning // 长时测试标记
@SpringBootTest
class LongRunningTest {
@Test
void testLongRunning() {
// 可能耗时的集成测试
}
}
14. 完整 Demo 示例
14.1 Hello World — 同步版
public class HelloWorldSync {
public static void main(String[] args) {
ConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
AmqpAdmin admin = new RabbitAdmin(connectionFactory);
admin.declareQueue(new Queue("myqueue"));
AmqpTemplate template = new RabbitTemplate(connectionFactory);
template.convertAndSend("myqueue", "foo");
String result = (String) template.receiveAndConvert("myqueue");
System.out.println("Received: " + result); // Received: foo
}
}
14.2 Hello World — 异步版(Spring Boot)
@SpringBootApplication
public class HelloWorldAsync {
public static void main(String[] args) {
SpringApplication.run(HelloWorldAsync.class, args);
}
// --- 生产者 ---
@Bean
public Queue helloQueue() {
return new Queue("hello.queue");
}
@Bean
public ApplicationRunner producer(RabbitTemplate template) {
return args -> {
for (int i = 0; i < 10; i++) {
template.convertAndSend("hello.queue", "Message #" + i);
}
System.out.println("10 messages sent.");
};
}
// --- 消费者 ---
@RabbitListener(queues = "hello.queue")
public void consumer(String message) {
System.out.println("Received: " + message);
}
}
14.3 订单处理系统(完整示例)
项目结构:
com.example.order ├── config │ └── RabbitConfig.java ├── model │ ├── Order.java │ └── OrderResult.java ├── service │ ├── OrderService.java │ └── NotificationService.java ├── listener │ └── OrderListener.java ├── controller │ └── OrderController.java └── OrderApplication.java
配置类:
@Configuration
public class RabbitConfig {
// ============ Connection ============
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
factory.setPublisherReturns(true);
return factory;
}
// ============ Exchanges ============
@Bean
public TopicExchange orderExchange() {
return ExchangeBuilder.topicExchange("order.exchange").durable(true).build();
}
@Bean
public DirectExchange dlxExchange() {
return new DirectExchange("order.dlx.exchange");
}
// ============ Queues ============
@Bean
public Queue orderCreateQueue() {
return QueueBuilder.durable("order.create.queue")
.withArgument("x-dead-letter-exchange", "order.dlx.exchange")
.withArgument("x-dead-letter-routing-key", "order.dead")
.build();
}
@Bean
public Queue orderDeadQueue() {
return QueueBuilder.durable("order.dead.queue").build();
}
@Bean
public Queue notificationQueue() {
return QueueBuilder.durable("order.notification.queue")
.withArgument("x-dead-letter-exchange", "order.dlx.exchange")
.withArgument("x-dead-letter-routing-key", "order.dead")
.build();
}
// ============ Bindings ============
@Bean
public Binding createBinding() {
return BindingBuilder.bind(orderCreateQueue())
.to(orderExchange()).with("order.created");
}
@Bean
public Binding deadBinding() {
return BindingBuilder.bind(orderDeadQueue())
.to(dlxExchange()).with("order.dead");
}
@Bean
public Binding notificationBinding() {
return BindingBuilder.bind(notificationQueue())
.to(orderExchange()).with("order.*");
}
// ============ RabbitTemplate ============
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(jackson2MessageConverter());
template.setConfirmCallback((correlationData, ack, cause) -> {
String id = correlationData != null ? correlationData.getId() : "unknown";
if (ack) {
log.info("订单消息确认: {}", id);
} else {
log.error("订单消息发送失败: {}, 原因: {}", id, cause);
}
});
template.setReturnsCallback(returned ->
log.error("订单消息退回到 {}:{} — {}",
returned.getExchange(), returned.getRoutingKey(),
new String(returned.getMessage().getBody()))
);
return template;
}
// ============ Listener Container ============
@Bean
public SimpleRabbitListenerContainerFactory orderListenerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setConcurrentConsumers(5);
factory.setMaxConcurrentConsumers(20);
factory.setPrefetchCount(50);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setMessageConverter(jackson2MessageConverter());
// 重试策略
RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(3)
.exponentialBackoff(1000, 2.0, 5000)
.build();
// 重试耗尽后发送到死信队列
MessageRecoverer recoverer = new RepublishMessageRecoverer(
rabbitTemplate(connectionFactory), "order.dlx.exchange", "order.dead");
factory.setRetryTemplate(retryTemplate);
factory.setRecoveryCallback(new RetryContextExhaustedMessageRecoverer(recoverer));
return factory;
}
@Bean
public Jackson2JsonMessageConverter jackson2MessageConverter() {
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
// 信任所有包(生产环境应限制)
converter.setClassMapper(new DefaultJackson2JavaTypeMapper());
return converter;
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
}
监听器:
@Component
@Slf4j
public class OrderListener {
@Autowired
private OrderService orderService;
@Autowired
private NotificationService notificationService;
@RabbitListener(queues = "order.create.queue",
containerFactory = "orderListenerFactory")
public void handleOrderCreated(
Order order,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey)
throws IOException {
log.info("收到订单创建消息: routingKey={}, order={}", routingKey, order.getId());
try {
// 业务处理
OrderResult result = orderService.processOrder(order);
// 手动确认
channel.basicAck(deliveryTag, false);
log.info("订单处理完成: {}", result);
} catch (OrderValidationException e) {
// 校验失败,不重试,发送到死信
log.warn("订单校验失败,移至死信: {}", order.getId());
channel.basicReject(deliveryTag, false); // requeue=false
} catch (Exception e) {
// 其他异常,重新入队等待重试
log.error("订单处理异常,重新入队: {}", order.getId(), e);
channel.basicNack(deliveryTag, false, true);
}
}
@RabbitListener(queues = "order.notification.queue")
public void handleNotification(Order order) {
// 所有订单事件都会触发通知(routing key = "order.*")
notificationService.sendNotification(order);
}
@RabbitListener(queues = "order.dead.queue")
public void handleDeadOrder(Order order) {
// 死信处理:记录到数据库、告警、人工介入
log.warn("死信订单,需人工处理: {}", order);
orderService.saveDeadOrder(order);
}
}
发送端(Controller):
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostMapping
public ResponseEntity<String> createOrder(@RequestBody Order order) {
CorrelationData correlationData = new CorrelationData(order.getId());
rabbitTemplate.convertAndSend(
"order.exchange",
"order.created",
order,
correlationData
);
return ResponseEntity.accepted().body("Order submitted: " + order.getId());
}
// 延迟订单(需安装 delayed message exchange 插件)
@PostMapping("/delayed")
public ResponseEntity<String> createDelayedOrder(@RequestBody Order order) {
rabbitTemplate.convertAndSend(
"order.exchange",
"order.delayed",
order,
msg -> {
msg.getMessageProperties().setDelay(30000); // 30s 延迟
return msg;
}
);
return ResponseEntity.accepted().body("Delayed order submitted");
}
}
14.4 股票交易示例
@Component
@Slf4j
public class StockTrading {
// === 市场数据发布者 ===
@Scheduled(fixedRate = 1000)
public void publishMarketData() {
MarketData data = MarketData.random();
rabbitTemplate.convertAndSend(
"stock.exchange",
"market." + data.getSymbol(),
data
);
}
// === 交易指令监听器 ===
@RabbitListener(queues = "stock.trade.queue")
public void handleTrade(TradeOrder order) {
log.info("执行交易: symbol={}, qty={}, price={}",
order.getSymbol(), order.getQuantity(), order.getPrice());
// 交易逻辑
}
// === 行情监听器(Topic Exchange 通配符) ===
@RabbitListener(queues = "stock.market.queue")
public void handleMarketData(
@Payload MarketData data,
@Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey) {
log.info("[{}] {}: ¥{}/{}",
routingKey, data.getSymbol(), data.getPrice(), data.getVolume());
}
}
15. 组件开发示例
15.1 自定义消息后处理器
@Component
public class TraceIdMessagePostProcessor implements MessagePostProcessor {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setHeader("X-Trace-Id", MDC.get("traceId"));
message.getMessageProperties().setHeader("X-Timestamp", Instant.now().toString());
return message;
}
@Override
public Message postProcessMessage(Message message, Correlation correlation) {
return postProcessMessage(message);
}
}
// 使用
template.convertAndSend("exchange", "key", payload, new TraceIdMessagePostProcessor());
15.2 自定义消息转换器
public class ProtobufMessageConverter implements MessageConverter {
@Override
public Message toMessage(Object object, MessageProperties messageProperties)
throws MessageConversionException {
if (object instanceof MessageLite) {
byte[] bytes = ((MessageLite) object).toByteArray();
messageProperties.setContentType("application/x-protobuf");
return new Message(bytes, messageProperties);
}
throw new MessageConversionException("Unsupported type: " + object.getClass());
}
@Override
public Object fromMessage(Message message) throws MessageConversionException {
// 需要知道目标类型,可通过 header 传递
String className = message.getMessageProperties().getHeader("__TypeId__");
// ...
return null;
}
}
15.3 自定义 ConnectionFactory 包装器
public class MetricsConnectionFactory extends AbstractConnectionFactory {
private final MeterRegistry meterRegistry;
private final CachingConnectionFactory delegate;
public MetricsConnectionFactory(CachingConnectionFactory delegate,
MeterRegistry meterRegistry) {
this.delegate = delegate;
this.meterRegistry = meterRegistry;
}
@Override
public Connection createConnection() throws AmqpException {
Timer.Sample sample = Timer.start(meterRegistry);
try {
Connection conn = delegate.createConnection();
sample.stop(meterRegistry.timer("rabbitmq.connection.create"));
return conn;
} catch (AmqpException e) {
meterRegistry.counter("rabbitmq.connection.error").increment();
throw e;
}
}
}
15.4 RabbitMQ Stream 插件使用
// 依赖:spring-rabbit-stream
@Configuration
public class StreamConfig {
@Bean
public Environment environment() {
return Environment.builder()
.host("localhost")
.port(5552) // Stream 插件端口
.username("guest")
.password("guest")
.build();
}
@Bean
public RabbitStreamTemplate streamTemplate(Environment env) {
RabbitStreamTemplate template = new RabbitStreamTemplate(env, "my-stream");
// 发送
template.convertAndSend(message);
return template;
}
@RabbitListener(queues = "my-stream") // Stream 队列
public void handleStreamMessage(String message) {
// 处理流消息
}
}
15.5 日志 Appender(AMQP Logback Appender)
<!-- logback-spring.xml --> <appender name="AMQP" class="org.springframework.amqp.rabbit.logback.AmqpAppender"> <host>localhost</host> <port>5672</port> <username>guest</username> <password>guest</password> <virtualHost>/</virtualHost> <exchangeName>logs.exchange</exchangeName> <routingKeyPattern>app.%level</routingKeyPattern> <declareExchange>true</declareExchange> <applicationId>my-service</applicationId> <charset>UTF-8</charset> <durable>true</durable> </appender>
16. 最佳实践清单
连接管理
-
✅ 使用 CachingConnectionFactory 管理连接/Channel 缓存,避免频繁创建
-
✅ 启用发布者确认(
publisher-confirm-type: correlated)和发布者返回(publisher-returns: true) -
✅ 配置 Channel 缓存大小,生产环境建议 50-100
-
✅ 启用心跳(
requested-heartbeat: 60s),防止空闲连接被中间网络设备断开 -
✅ 集群部署使用
addresses属性,避免单点 -
✅ 启用自动恢复,Broker 重启后自动重连
消息发送
-
✅ 使用
convertAndSend(),让消息转换器处理序列化 -
✅ 设置 CorrelationData,将业务 ID(如订单号)关联到确认回调
-
✅ 实现 ConfirmCallback 和 ReturnsCallback,监控消息是否成功到达 Broker
-
✅ 批量发送使用
BatchingRabbitTemplate减少网络开销 -
✅ 传递头信息使用
MessagePostProcessor,如 trace-id、timestamp
消息接收
-
✅ 使用 @RabbitListener 替代编程式监听,代码更简洁
-
✅ 选择合适的容器:Simple(事务/多队列)vs Direct(高吞吐/低延迟)
-
✅ 合理设置并发:
concurrency(初始 3-5)、max-concurrency(峰值 10-20) -
✅ 合理设置 prefetch:高吞吐场景 100-500,低延迟场景 1-10
-
✅ 批处理场景启用
batchListener=true和consumerBatchEnabled=true -
✅ 手动确认模式(MANUAL) 在处理成功后显式 ACK
消息序列化
-
✅ 使用 Jackson2JsonMessageConverter 作为默认转换器
-
✅ 生产环境限制信任包(
setTrustedPackages),防止反序列化漏洞 -
✅ 通过消息头传递类型信息(
__TypeId__),确保类型安全反序列化 -
✅ ContentTypeDelegatingMessageConverter 支持多格式消息路由
异常处理与重试
-
✅ 区分可重试异常与致命异常:临时异常重试,业务校验失败直接拒绝
-
✅ 使用指数退避(exponential backoff) 代替固定间隔重试
-
✅ 配置死信队列(DLX):重试耗尽后的消息进入死信,便于排查和补偿
-
✅ 使用 RepublishMessageRecoverer 自动将失败消息重新发布
-
✅ 重试次数建议 3-5 次,总退避时间不超过消息 TTL
事务
-
✅ 需要原子性操作时才使用事务(如多个队列的发送必须在同一事务中)
-
✅ 事务性能开销大,优先使用发布者确认 + 手动 ACK 保障可靠性
-
✅ SimpleMessageListenerContainer 支持事务,Direct 不支持
Broker 配置
-
✅ 使用 Builder API(
ExchangeBuilder、QueueBuilder)声明资源 -
✅ 队列设置为持久化(
durable=true),消息持久化发送 -
✅ Quorum Queue 替代 Classic Mirrored Queue(RabbitMQ 3.8+)
-
✅ 设置队列 TTL 和最大长度,防止消息堆积
-
✅ 使用 RabbitAdmin 的自动声明,Broker 恢复后自动重建拓扑
监控与运维
-
✅ 引入 Micrometer,监控消息发送/消费速率、延迟、错误率
-
✅ BrokerEventListener 监听 Broker 可用性变化
-
✅ 死信队列监控告警:DLQ 中有消息即告警
-
✅ 连接池监控:Channel 获取超时、连接创建失败计数
测试
-
✅ 单元测试使用
TestRabbitTemplate和RabbitListenerTestHarness -
✅ 集成测试使用
@SpringRabbitTest+@RabbitAvailable(JUnit5) -
✅ Mock RabbitTemplate 在 Service 层测试中隔离 AMQP 依赖
安全
-
✅ 启用 SSL/TLS 加密传输
-
✅ 限制 Jackson 反序列化信任包
-
✅ 使用单独的用户凭据,按最小权限原则分配 vhost 权限
-
✅ 生产环境关闭管理端口公网访问(15672)
附录:Maven 完整依赖
<dependencies> <!-- Spring AMQP 核心 --> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>3.0.4</version> </dependency> <!-- RabbitMQ Stream 插件支持 --> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit-stream</artifactId> <version>3.0.4</version> </dependency> <!-- Jackson JSON 支持 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- Spring Retry(重试支持) --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <!-- Micrometer(可观测性) --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-core</artifactId> </dependency> <!-- Spring Boot Starter(推荐) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <!-- 测试 --> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit-test</artifactId> <scope>test</scope> </dependency> </dependencies>
参考资料:
springdoc.cn/spring-amqp — Spring AMQP 中文文档(版本 3.0.4-SNAPSHOT)
docs.spring.io/spring-amqp/reference — 官方参考文档(版本 4.0.3)
spring.io/projects/spring-amqp — Spring AMQP 项目主页
1518

被折叠的 条评论
为什么被折叠?



