带解码器问题的Kafka Avro Consumer

时间:2016-03-15 21:18:29

标签: java apache-kafka avro kafka-consumer-api apache-nifi

当我尝试使用我各自的架构运行Kafka Consumer with Avro数据时,它会返回错误“AvroRuntimeException:格式错误的数据。长度为负数:-40”。我看到其他人遇到了类似的问题converting byte array to jsonAvro write and readKafka Avro Binary *coder。我也引用了这个Consumer Group Example,它们都很有帮助,但到目前为止还没有帮助解决这个错误。 它一直工作到代码的这一部分(第73行)

解码器解码器= DecoderFactory.get()。binaryDecoder(byteArrayInputStream,null);

我已经尝试过其他解码器并打印出byteArrayInputStream变量的内容,它看起来我相信你会期望序列化的avro数据看起来(在消息中我可以看到模式和一些数据和一些格式错误的数据)我有使用.available()方法打印出可用的字节数,该方法返回594.我无法理解为什么会发生此错误。 Apache Nifi用于生成具有来自hdfs的相同模式的Kafka流。我将不胜感激任何帮助。

1 个答案:

答案 0 :(得分:17)

问题可能是Nifi如何编写(编码)Avro数据与消费者应用程序读取(解码)数据的方式不匹配。

简而言之,Avro的API提供了两种不同的序列化方法:

  1. 用于创建正确的Avro 文件:对数据记录进行编码,同时将Avro架构嵌入到一种前导码中(通过org.apache.avro.file.{DataFileWriter/DataFileReader})。将模式嵌入到Avro文件中非常有意义,因为(a)通常是"有效负载" Avro文件的数量级大于嵌入式Avro架构的数量级;(b)然后您可以根据自己的内容复制或移动这些文件,并且仍然可以确保您可以再次阅读这些文件而无需咨询某人或某事
  2. 仅编码数据记录,即不嵌入架构(通过org.apache.avro.io.{BinaryEncoder/BinaryDecoder};请注意包名称的不同之处:io此处与file之上的差异。例如,当Avro编码正在写入Kafka主题的消息时,这种方法通常很受欢迎,因为与上面的变体1相比,您不会产生将Avro架构重新嵌入到每个消息中的开销,假设您的(非常合理)策略是,对于相同的Kafka主题,消息使用相同的Avro架构进行格式化/编码。这是一个显着的优点,因为在流数据上下文中,动态数据记录通常比如上所述的静态数据Avro文件小得多(通常在100字节到几百KB之间)(通常是数百或者数千MB);因此,Avro架构的大小相对较大,因此在向Kafka写入2000个数据记录时,您不希望将其嵌入2000x。缺点是你必须以某种方式"跟踪Avro架构如何映射到Kafka主题 - 或者更确切地说,您必须以某种方式跟踪编码消息的Avro架构,而不必直接嵌入架构的路径。好消息是tooling available in the Kafka ecosystem (Avro schema registry)透明地执行此操作。因此,与变体1相比,变体2以提高便利性为代价获得了效率。
  3. 效果是"线格式"对于编码的Avro数据,看起来会有所不同,具体取决于您是使用上面的(1)还是(2)。

    我对Apache Nifi不太熟悉,但快速查看源代码(例如ConvertAvroToJSON.java)向我建议它使用变量1,即它将Avro架构与Avro记录一起嵌入。但是,您的使用者代码使用DecoderFactory.get().binaryDecoder(),因此使用变体2(未嵌入架构)。

    也许这解释了您遇到的错误?