【问题标题】:What is the proper way of doing @DirtiesConfig when used @EmbeddedKafka使用@EmbeddedKafka 时做@DirtiesConfig 的正确方法是什么
【发布时间】:2020-01-30 21:17:57
【问题描述】:

我们的项目中有一个“小”问题:“无法建立到节点 0 的连接。代理可能不可用。”测试运行的时间非常长,并且每秒至少记录一次此消息。但我发现,如何摆脱它。继续阅读。如果配置/注释中有不正确的地方,请告诉我。

版本优先:

<springframework.boot.version>2.1.8.RELEASE</springframework.boot.version>

自动带来

<spring-kafka.version>2.2.8.RELEASE</spring-kafka.version>

现在我们将考虑由以下注释的集成测试:

@RunWith(SpringRunner.class)
@Import(/*some our configuration, irrelevant*/ )
@ActiveProfiles(/*some our profiles, irrelevant*/)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EmbeddedKafka(controlledShutdown = true)
@Transactional

然后我们在其中进行了一些测试,例如:

@Test
@DirtiesContext

public void testPostWhatever() throws JSONException, IOException {

这个测试只是创建一些请求数据,调用 post,然后将数据持久化到 DB 中。然后我们将使用 GET 来查找,是否可以找到这些数据。琐碎的。对我来说有点奇怪的是这里的事务处理。测试类使用@Transactional 注释,但根据日志事务仅在Controller 方法上打开,在此示例中(它应该在服务中,当然)相同的@Transactional 注释。两者都带有 TxType.REQUIRED 传播。这将导致测试发起的回滚实际上没有回滚,因为事务已经提交。如果你知道,为什么会这样,请指教。但这不是这个问题的症结所在。到目前为止,我们只是将@DirtiesContext 放在这个方法上,它应该只是重新初始化上下文。它以高昂的上下文重新初始化成本解决了未回滚数据的问题。但以下消息开始出现在日志中:

2019-10-01 13:49:07.336 org.apache.kafka.clients.NetworkClient   : [Producer clientId=producer-2] Connection to node 0 could not be established. Broker may not be available.
2019-10-01 13:49:07.699 org.apache.kafka.clients.NetworkClient   : [Producer clientId=producer-1] Connection to node 0 could not be established. Broker may not be available.
2019-10-01 13:49:08.191 org.apache.kafka.clients.NetworkClient   : [Producer clientId=producer-2] Connection to node 0 could not be established. Broker may not be available.
2019-10-01 13:49:08.603 org.apache.kafka.clients.NetworkClient   : [Producer clientId=producer-1] Connection to node 0 could not be established. Broker may not be available.
2019-10-01 13:49:08.927 o.a.c.loader.WebappClassLoaderBase       : The web application [ofs] appears to have started a thread named [kafka-producer-network-thread | producer-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
 sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
 sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
 sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
 sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
 org.apache.kafka.common.network.Selector.select(Selector.java:691)
 org.apache.kafka.common.network.Selector.poll(Selector.java:411)
 org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:510)
 org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:239)
 org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:163)
 java.lang.Thread.run(Thread.java:748)

删除此@DirtiesContext 并将其置于类级别,如

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)

具有相同的行为(除了可笑的额外开销)。但是如果我删除所有@DirtiesContext,并手动清除数据库并提交更改,以便在每次测试后还原更改,一切正常,没有警告或错误。

所以我认为有两件事。我的问题是由不正确的 tx 处理引起的(请帮助),但 @DirtiesContext 应该也可以与 spring-kafka 一起使用,并且 似乎 不起作用。原则上不可能(或者是?),或者我的某些配置不正确(请帮助),或者它可能是一个错误?

【问题讨论】:

    标签: spring-boot spring-kafka spring-kafka-test


    【解决方案1】:

    如果您使用的是 JUnit4,则可以将 EmbeddedKafkaRule 用作 @ClassRule 而不是使用 @EmbeddedKafka,然后不会将代理添加到上下文中。

    不幸的是,JUnitt5 没有等效项 - 但您仍然可以添加静态 EmbeddedKafkaBroker 并在 @AfterAll 方法中自行销毁它。

    【讨论】:

    • 感谢您的回答。我试过了,它似乎有助于“[Producer clientId=producer-2] 无法建立到节点 0 的连接。代理可能不可用。”日志消息(这会造成大部分混乱和可能的问题)但错误:“Web 应用程序 [ofs] 似乎已经启动了一个名为 [kafka-producer-network-thread | producer-2] 的线程”似乎仍然存在。所以这是改进,但不是完整的解决方案。以防您确实需要将上下文标记为脏。
    • 删除所有@DirtiesContext 解决了所有问题,但我不确定这对于不能在集成测试中删除这些注释的人来说是否不是问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多