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

时间:2016-12-27 09:43:26

标签: apache-kafka apache-kafka-streams

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

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。

注意:我可以轻松地设置一个自定义时间戳提取器,它可以检查每条消息中的负时间戳,但这对我的应用来说是很多不必要的开销。我想要了解的是,在检测到带有负时间戳的消息后,为什么流没有进展。

1 个答案:

答案 0 :(得分:4)

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

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

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

如何修复:

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

我没有解释为什么你得到了无效的时间戳...这很奇怪你可能想调查你的生产者设置并试图找出你的生产者是否有可能放置和无效的时间戳(即使这个不太可能 - 我不知道问题的根本原因是什么。)

进一步评论:

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