StreamsException:提取的时间戳值为负数,这是不允许的

StreamsException: Extracted timestamp value is negative, which is not allowed

这可能是 Error in Kafka Streams using kafka-node - negative timestamp 的重复,但肯定不是。我的 Kafka Streams 应用程序对每条消息执行一些转换逻辑并将其转发到新主题。应用程序中没有基于时间的 aggregation/processing,因此无需使用任何自定义时间戳提取器。此应用 运行 好几天都正常,但突然间该应用抛出了一个负时间戳异常。

Exception in thread "StreamThread-4" org.apache.kafka.streams.errors.StreamsException: Extracted timestamp value is negative, which is not allowed.

从所有 StreamThreads(总共 10 个)抛出此异常后,应用程序有点冻结,因为数小时内流没有进一步的进展。之后没有抛出异常。当我重新启动应用程序时,它开始只处理新收到的消息。

现在的问题是,中间出现的那些消息发生了什么(抛出异常之后和重新启动应用程序之前)。以防万一,那些丢失的消息没有嵌入时间戳(这是极不可能的,因为代理和生产者没有发生任何变化),难道应用程序不应该为每条这样的消息抛出异常吗?或者是不是应用程序在第一次检测到消息中的负时间戳时停止流进程?有没有办法处理这种情况,以便即使在检测到任何负时间戳后,应用程序也可以继续流?我的应用程序使用 Kafka Streams 库版本 0.10.0.1-cp1。

注意:我可以很容易地建立一个自定义时间戳提取器,它可以检查每条消息中的负时间戳,但这对我的应用程序来说是很多不必要的开销。我只想了解为什么在检测到具有负时间戳的消息后流没有进行。

即使您没有任何基于时间的运算符,Kafka Streams 应用程序也会检查从时间戳提取器 return 提取的时间戳是否有效,因为时间戳用于确定来自不同分区的记录的处理顺序,以确保记录按顺序处理,并且所有分区都以基于时间的对齐方式使用。

如果检测到负时间戳,则应用程序(或实际上是相应的线程)终止。不幸的是,目前无法从此类异常中恢复,您需要重新启动您的应用程序。另请参阅 Confluent 常见问题解答:http://docs.confluent.io/3.1.1/streams/faq.html#invalid-timestamp-exception

如果您的应用程序死机并且您重新启动它,它将从中断处继续处理。不幸的是,在 Kafka 0.10.0.1 中存在一个错误(在即将发布的版本 0.10.2 中修复)并且在失败的情况下可能会提交不正确的偏移量并且应用程序 "steps over" 一些记录。我假设这发生在您的情况下,并且如果您只有一些记录的时间戳无效,则这些记录可能已被跳过,从而允许您的应用程序在重新启动后恢复。这种行为实际上是一个错误——如果没有这个错误,Kafka Stream 会一次又一次地尝试处理那些具有无效时间戳的记录,并且每次都失败,直到你提供一个自定义时间戳提取器,通过 returning 一个有效的来解决这个问题时间戳。

如何解决:

正确的解决方法是提供一个自定义时间戳提取器,它永远不会 return 无效(即负的)时间戳。

我无法解释为什么你得到无效的时间戳...这很奇怪,你可能想调查你的生产者设置并试图弄清楚你的生产者是否有可能放置和无效的时间戳(甚至如果这不太可能——我不知道问题的根本原因可能是什么。

进一步说明:

在下一个版本 (0.10.2) 中,处理无效时间戳得到简化,Kafka Streams 提供更多内置时间戳提取器,以不同方式处理具有无效时间戳的记录。例如,这允许您自动跳过具有无效时间戳的记录,而不是引发错误(当前行为)。有关详细信息,请参阅 KIP-93:https://cwiki.apache.org/confluence/display/KAFKA/KIP-93%3A+Improve+invalid+timestamp+handling+in+Kafka+Streams