[英]spring-amqp transaction semantics
我目前正在测试一个关于与spring amqp的数据库事务相关的消息传递事务的一个相当简单的例子。
用例如下:
数据库已更新
@Transactional public void handleMessage(EventPayload event) { MyEntity entity = new MyEntity(); entity.setName(event.getName()); rabbitTemplate.convertAndSend("myExchange", "payload.create", payload); MyEntity savedEntity = entityRepository.save(entity); }
在数据库操作期间发生故障时的预期行为是收到的消息回滚到总线(DefaultRequeueRejected = false)并进入死信队列。 发送的消息也应该回滚。
我可以通过以下配置实现此目的:
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter);
rabbitTemplate.setChannelTransacted(true);
return rabbitTemplate;
}
@Bean
SimpleMessageListenerContainer subscriberListenerContainer(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter,
PlatformTransactionManager transactionManager) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(SUBSCRIBER_QUEUE_NAME);
container.setMessageListener(listenerAdapter);
container.setChannelTransacted(true);
container.setTransactionManager(transactionManager);
container.setDefaultRequeueRejected(false);
return container;
}
所以这很好 - 我不明白的是,如果我没有在SimpleMessageListenerContainer
上设置事务管理器,观察到的行为是完全相同的。 因此,如果我配置以下bebavior不会改变:
@Bean
SimpleMessageListenerContainer subscriberListenerContainer(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(SUBSCRIBER_QUEUE_NAME);
container.setMessageListener(listenerAdapter);
container.setDefaultRequeueRejected(false);
return container;
}
有人能解释那里发生了什么吗? 为什么第二种情况也有效? 如果PlatformTransactionManager
在SimpleMessageListenerContainer
上注册,那么内部会有什么不同。
假设transactionManager
是你的数据库tm,因为你的监听器是@Transactional
,所以这些场景没有太大的区别。
在第一种情况下,事务在调用侦听器之前由容器启动(实际上在从内部队列检索消息之前,因此即使没有消息也会启动事务)。
在第二种情况下,当我们调用侦听器时,事务拦截器启动事务。
考虑一下监听器不是事务性的情况,但是某些下游组件是; 假设侦听器成功调用该组件,然后在抛出异常之前再做一些工作。 在这种情况下,数据库提交将成功并且消息被拒绝。 这可能不是理想的行为,特别是如果消息被重新排队。 在这种情况下,通常通过注入数据库tm来使兔子事务与数据库事务同步更好。
在你的情况下,数据库提交和兔子确认之间几乎没有机会失败,所以这真的不适用于你的情况,你不需要容器中的tm。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.