繁体   English   中英

如何将@Transactional 与@KafkaListener 一起使用?

[英]How to use @Transactional with @KafkaListener?

是否有可能将声明性 tx 管理(通过 @Transactional)与 @KafkaListener 注释方法一起使用? 例如,我想使用它来为每个侦听器定义单独的 tx 超时。 我的设置如下:

事务管理器:

@Bean
        @ConditionalOnBean(value = {HibernateTransactionManager.class})
        public ChainedKafkaTransactionManager<Object, Object> chainedHibernateTm(KafkaTransactionManager<String, String> kafkaTransactionManager,
                                                                                 org.springframework.orm.hibernate5.HibernateTransactionManager hibernateTransactionManager) {
            return new ChainedKafkaTransactionManager<>(kafkaTransactionManager, hibernateTransactionManager);
        }

卡夫卡监听器:

@KafkaListener(topic = "my_topic")
@Transactional(timeout = 5)
public void handleMessage(SomeMessage message){
}

问题是 - KafkaMessageListenerContainer 在调用此类方法之前创建自己的事务 - 它使用自己的 TransactionTemplate:

@Nullable
        private TransactionTemplate determineTransactionTemplate() {
            return this.transactionManager != null
                    ? new TransactionTemplate(this.transactionManager)
                    : null;
        }

不使用 TransactionInterceptor。 那么如何为具体的@KafkaListener 方法设置特定的 tx 超时呢?

可以做到,但有点复杂,因为您必须将消耗的偏移量发送到 Kafka 事务。

您可以将KafkaTransactionManager用于容器,将@Transactional用于HibernateTransactionManager ,而不是使用ChainedKafkaTransactionManager

这将给出类似的结果,因为 hibernate TX 将在 Kafka 事务之前提交(如果 hibernate 提交失败,Kafka TX 将回滚)。

编辑

要将不同的链式 TM 配置到每个侦听器容器中,您可以执行以下操作。

@Component class ContainerFactoryCustomizer {

ContainerFactoryCustomizer(AbstractKafkaListenerContainerFactory<?, ?, ?> factory,
        ChainedKafkaTransactionManager<?, ?> chainedOne,
        ChainedKafkaTransactionManager<?, ?> chainedTwo) {
    factory.setContainerCustomizer(
            container -> {
                String groupId = container.getContainerProperties().getGroupId();
                if (groupId.equals("foo")) {
                    container.getContainerProperties().setTransactionManager(chainedOne);
                }
                else {
                    container.getContainerProperties().setTransactionManager(chainedTwo);
                }
            });
}

}


Where each chained TM has a Hibernate TM with a different default timeout.

The `groupid` is populated from the `@KafkaListener` `id` or `groupId` property.

通过普通的@Transactional进行事务管理的方面并不像您想要的那样与 Kafka 侦听器一起工作 - 没有内置的交互。

有一个专门的章节如何在事务中使用应用程序事件:使用注释@TransactionalEventListener事务绑定事件有助于确保事务已成功完成。

您可以使用 @EventListener 注释注册常规事件侦听器。 如果需要将其绑定到事务,请使用@TransactionalEventListener。 当您这样做时,默认情况下侦听器绑定到事务的提交阶段。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM