我们对 Kafka 有一个标准设置,我们使用 @KafkaLisetener 来监听某个主题上的事件,并使用 KafkaTemplate 将响应发送到另一个主题。
为了提高吞吐量,我们将请求和响应通道上的分区增加到 4。之后,我们开始看到响应通道上收到的消息有接近 30 秒的延迟。
对日志进行进一步调查后,我们发现这 30 秒的大部分时间都被生产者占用,试图更新与其尝试发布到的主题相关的元数据。
我们看到类似下面的日志(机密信息省略)
2023-11-07 11:30:14.873 INFO 1 --- [tainer#61-0-C-1] i.h.microserviceName.consumer.WalletEvent : [7e3c5513-fe7a-443f-a888-6b19b37840b2] - inside send
2023-11-07 11:30:45.013 INFO 1 --- [ad | producer-1] org.apache.kafka.clients.Metadata : [Producer clientId=producer-1] Resetting the last seen epoch of partition microserviceName.moduleName.functionName.res-0 to 0 since the associated topicId changed from null to C85tFo-jRJWrZAvVkJnOkw
2023-11-07 11:30:45.013 INFO 1 --- [ad | producer-1] org.apache.kafka.clients.Metadata : [Producer clientId=producer-1] Resetting the last seen epoch of partition microserviceName.moduleName.functionName.res-2 to 0 since the associated topicId changed from null to C85tFo-jRJWrZAvVkJnOkw
2023-11-07 11:30:45.013 INFO 1 --- [ad | producer-1] org.apache.kafka.clients.Metadata : [Producer clientId=producer-1] Resetting the last seen epoch of partition microserviceName.moduleName.functionName.res-3 to 0 since the associated topicId changed from null to C85tFo-jRJWrZAvVkJnOkw
2023-11-07 11:30:45.014 INFO 1 --- [ad | producer-1] org.apache.kafka.clients.Metadata : [Producer clientId=producer-1] Resetting the last seen epoch of partition microserviceName.moduleName.functionName.res-1 to 0 since the associated topicId changed from null to C85tFo-jRJWrZAvVkJnOkw
2023-11-07 11:30:45.014 INFO 1 --- [tainer#61-0-C-1] i.h.microserviceName.consumer.WalletEvent : [7e3c5513-fe7a-443f-a888-6b19b37840b2] - Response sent for operation
生成此类日志的代码类似于以下内容:
void produce(...) {
log.info("inside send");
kafkaTemplate.send(....);
log.info("Response sent for operation");
}
如果我们查看时间戳,就会发现 log.info 语句的发生间隔几乎为 30 秒。在这期间我们的代码被完全阻止,之后我们从
org.apache.kafka.clients.Metadata
获取一些日志语句,指定一些元数据已更新。
是否有任何具体原因导致 Spring Kafka 需要 30 秒才能更新单个主题的元数据?无论如何,是否可以在后台执行此操作,而不是在制作人尝试制作某些内容时执行此操作?这样元数据就已经准备好了。
在我们的用例中,代理和分区的数量在整个过程中大部分都是相同的,因此我们也可以接受一些陈旧的元数据。
我们希望这个过程很快发生,我们的组织中还有一些其他微服务在 Nodejs 上运行并使用 Kafkajs 库,并以与具有 4 个分区的主题类似的方式生成,但我们在这些微服务中从未遇到过问题。
我们可接受的解决方案是可以在后台定期执行此操作,并且不影响任何
produce
调用。或者,即使 Spring Kafka 必须执行此元数据刷新,它也应该比 30 秒快得多。在我们的任何操作中添加 30 秒的延迟都是不可接受的。
看来我也遇到了同样的问题。找到根本原因了吗?