延迟卡夫卡流的消费

时间:2019-12-09 13:03:28

标签: java kotlin apache-kafka apache-kafka-streams

我正在尝试使用 Kafka Streams (不是简单的Kafka使用者)从重试主题中读取以前无法处理的事件。我希望从重试主题开始使用,并且如果处理仍然失败(例如,如果外部系统出现故障),我希望将事件放回重试主题。因此,我不想立即消耗,而要在消耗之前稍等片刻,以免系统中出现暂时无法处理的消息。

简化后,代码当前正在执行此操作,我希望对此添加一个延迟。

fun createTopology(topic: String): Topology {
    val streamsBuilder = StreamsBuilder()

    streamsBuilder.stream<String, ArchivalData>(topic, Consumed.with(Serdes.String(), ArchivalDataSerde()))
        .peek { key, msg -> logger.info("Received event for key $key : $msg") }
        .map { key, msg -> enrich(msg) }
        .foreach { key, enrichedMsg -> archive(enrichedMsg) }

    return streamsBuilder.build()
}

我尝试使用“窗口延迟”进行此设置,但没有设法使其正常工作。我当然可以在peek内入睡,但是那样会使线程挂起,而且听起来不是很干净的解决方案。

关于延迟如何工作的确切细节对于我的用例而言并不十分重要。例如,所有这些都可以正常工作:

  1. 过去x秒内有关该主题的所有事件都被一次消耗掉。在开始消费/完成消费后,流将等待x秒,然后再次消费
  2. 每个事件在被置于主题上之后x秒被处理
  3. 流消耗消息的时间间隔为每个事件之间x

如果有人可以提供几行可以完成以上任何一项功能的Kotlin或Java代码,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

您不能真正使用Kafka Streams暂停从输入主题中读取内容,“延迟”的唯一方法是调用“睡眠”,但是正如您提到的那样,这阻塞了整个线程,不是一个好的解决方案。 / p>

但是,您可以做的是使用有状态处理器,例如process()(带有附加状态存储)而不是foreach()。如果重试失败,则不会将记录放回输入主题中,而是将其放到存储中,并且还要注册具有期望的重试延迟的标点符号。如果标点符号被触发,则重试;如果重试成功,则从存储中删除条目并取消标点符号;否则,您要等到标点再次触发。