Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何最好地处理KafkaConsumer轮询方法中的SerializationException_Java_Apache Kafka_Kafka Consumer Api - Fatal编程技术网

Java 如何最好地处理KafkaConsumer轮询方法中的SerializationException

Java 如何最好地处理KafkaConsumer轮询方法中的SerializationException,java,apache-kafka,kafka-consumer-api,Java,Apache Kafka,Kafka Consumer Api,在Kafka中的消费者轮询循环中,当轮询方法引发SerializationException时,是否有方法跳过此消息(也称为“毒丸”),继续消费主题中的下一个事件 我可以捕获异常并使用consumer.seek()方法将偏移量移动到下一条消息,但该方法需要分区和偏移量作为输入参数。有没有办法得到这些值 我在github repos中有示例代码。要运行该示例,请执行以下操作: $ git clone https://github.com/bjornhjelle/kafka-streams-exam

在Kafka中的消费者轮询循环中,当轮询方法引发SerializationException时,是否有方法跳过此消息(也称为“毒丸”),继续消费主题中的下一个事件

我可以捕获异常并使用consumer.seek()方法将偏移量移动到下一条消息,但该方法需要分区和偏移量作为输入参数。有没有办法得到这些值

我在github repos中有示例代码。要运行该示例,请执行以下操作:

$ git clone https://github.com/bjornhjelle/kafka-streams-examples-gradle.git
$ cd kafka-streams-examples-gradle
$ ./gradlew build -x test
$ ./gradlew test --tests no.test.SerializationExceptionExample
该示例为卡夫卡生成了三个事件。第二个事件导致SerializationException。捕获并记录异常。此时,我想将偏移量移过此事件。相反,在轮询循环中再次抛出。因此,第三个事件不会被消耗,因此测试失败

我知道关于同一主题的这个公开问题,但它提到卡夫卡客户端版本<0.10.0.1,而我使用的是1.0.0版本:

我还意识到,我可能可以通过使用卡夫卡流和处理毒药的新功能来解决这个问题()

让我首先研究这个问题的是这个例外: (示例代码导致不同的SerializationException,因为我无法重新创建此异常)


我找到的解决方案是解析序列化异常消息以获取所需的数据。主题名称、分区和偏移量:

catch (SerializationException se) {
                String s = se.getMessage().split("Error deserializing key/value for partition ")[1].split(". If needed, please seek past the record to continue consumption.")[0];
                String topic = s.split("-")[0];
                int offset = parseInt(s.split("offset ")[1]);
                int partition = parseInt(s.split("-")[1].split(" at")[0]);

                TopicPartition topicPartition = new TopicPartition(topic, partition);
                logger.debug("Skipping {}-{} offset {}", topic, partition , offset);
                consumer.seek(topicPartition, offset + 1L);}

如果您使用的是消费者组,并且捕捉到了异常,那么当您继续进行轮询时,消费者不会继续前进吗?我使用的是消费者组,但我看不出这有什么帮助。一个分区只分配给消费者组中的一个消费者,因此坏消息仍然会阻止来自该分区的更多消息的消费,直到我能够以某种方式将偏移量移动到当前偏移量之后。如果我没有捕获异常而让进程失败,那么分区将被重新分配给组中的另一个使用者,然后该使用者将遇到与坏消息相同的问题。(如果我错了,请更正…>“直到我能够以某种方式移动偏移”。如果捕获到异常,而使用者没有崩溃,它就不会继续读取和处理?对于消费者组,消费者“移动偏移”。如果您也捕获到了异常,不会发生这种情况吗?不,如果我捕获到异常,则偏移量不会提交,因为异常来自poll方法,因此消息没有正确使用。如果我没有捕获异常,但让应用程序退出,也是一样的。由于已达到保留期,邮件将一直保持可再次使用的状态,直到过期。所以在那之前,所有其他的消耗都会被“阻止”在那个分区上。我明白了。对不起,我从来没有处理过这件事。是的,你应该能够手动搜索/提交,也许?正如您在问题中所说,这要求您知道偏移量/分区,您可以随着消费者的进步跟踪它。当你点击异常时,你会知道最后一条消息是好的。这是可行的,但不是可靠的方法,因为它取决于来自异常的实际消息。因此,您可以在这里看到一个更好的选择:在反序列化程序本身中捕获异常,然后在consumerRecords循环中相应地处理结果。不建议这样做。如果主题名称中有“-”,那么它可能会非常不稳定。
catch (SerializationException se) {
                String s = se.getMessage().split("Error deserializing key/value for partition ")[1].split(". If needed, please seek past the record to continue consumption.")[0];
                String topic = s.split("-")[0];
                int offset = parseInt(s.split("offset ")[1]);
                int partition = parseInt(s.split("-")[1].split(" at")[0]);

                TopicPartition topicPartition = new TopicPartition(topic, partition);
                logger.debug("Skipping {}-{} offset {}", topic, partition , offset);
                consumer.seek(topicPartition, offset + 1L);}