Spring Kafka嵌套单元测试触发ProducerFencedException问题排查与解决
Spring-Kafka-Test 3.0.6 嵌套测试触发ProducerFencedException的解决方案
问题场景
使用spring-kafka-test 3.0.6进行单元测试时,包含两个嵌套测试用例Test1和Test2(Test1先执行,Test2后执行),每次测试几乎都会触发ProducerFencedException。
测试代码示例
@Test @Nested inner class Test1 { fun test1() { mypublisher.publishInTransaction(topic1) // see log1 // check listener1 // see log2 } } @Test @Nested inner class Test2 { fun test2() { mypublisher.publishInTransaction(topic2) // see log3 // check listener2 } } fun MyPublisher.publishInTransaction(topic: String) { // producerOnlyKafkaTemplate是KafkaTemplate实例 producerOnlyKafkaTemplate.executeInTransaction { producerOnlyKafkaTemplate.send(topic, "test-message") } }
问题原因分析
从日志中可以观察到:
Test1中创建的Producer(如Producer@58bb6ba7)提交事务后被关闭Test2复用该Producer时,提交事务触发ProducerFencedException
进一步排查发现,本应是单例的MyProducerOnlyFactory Bean被初始化了两次,导致同一个transactionalId关联了两个ProducerFactory实例:
MyProducerOnlyFactory-1创建的Producer提交事务后被放回缓存MyProducerOnlyFactory-2复用该Producer并将其producerEpoch更新为1- 后续
MyProducerOnlyFactory-1再次获取该Producer时,仍认为其epoch为0,提交事务时因epoch不匹配触发异常
解决方案
在测试类上添加@NestedTestConfiguration(NestedTestConfiguration.EnclosingConfiguration.OVERRIDE)注解,确保MyProducerOnlyFactory Bean仅被初始化一次:
@NestedTestConfiguration(NestedTestConfiguration.EnclosingConfiguration.OVERRIDE) class YourTestClass { // 嵌套测试用例Test1、Test2 }
内容的提问来源于stack exchange,提问作者jon
相关产品推荐
相关产品推荐

