我如何使用嵌入式模式从Kafka反序列化Avro

时间:2017-06-01 13:12:32

标签: apache-kafka apache-storm avro

我从Kafka主题收到二进制Avro文件,我必须反序列化它们。在Kafka收到的消息中,我可以在每条消息的开头看到一个模式。我知道更好的做法是不嵌入架构并将其与实际的Avro文件分开,但我无法控制生产者,我无法改变它。

我的代码运行在Apache Storm之上。首先,我创建了一个读者:

mDatumReader = new GenericDatumReader<GenericRecord>();

后来我尝试在不声明架构的情况下反序列化消息:

Decoder decoder = DecoderFactory.get().binaryDecoder(messageBytes, null);
GenericRecord payload = mDatumReader.read(null, decoder);

但是当消息到达时我收到错误:

Caused by: java.lang.NullPointerException: writer cannot be null!
at org.apache.avro.io.ResolvingDecoder.resolve(ResolvingDecoder.java:77) ~[stormjar.jar:?]
at org.apache.avro.io.ResolvingDecoder.<init>(ResolvingDecoder.java:46) ~[stormjar.jar:?]
at org.apache.avro.io.DecoderFactory.resolvingDecoder(DecoderFactory.java:307) ~[stormjar.jar:?]
at org.apache.avro.generic.GenericDatumReader.getResolver(GenericDatumReader.java:122) ~[stormjar.jar:?]
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:137) ~[stormjar.jar:?]

我所看到的所有答案都是关于使用其他格式,更改传递给Kafka或其他内容的消息。我无法控制这些事情。

我的问题是,如果bytes[]中的消息包含二进制消息中的嵌入式架构,那么如何在不声明架构的情况下反序列化该Avro文件,以便我可以阅读它。

2 个答案:

答案 0 :(得分:2)

使用DatumReader / Writer,没有像嵌入式架构那样的东西。看着Avro&amp; amp;是我的误会卡夫卡也是第一次。但是Avro Serializer的源代码清楚地表明在使用GenericDatumWriter时没有嵌入模式。

数据文件编写器在文件开头编写架构,然后使用GenericDatumWriter添加GenericRecords。

由于您说开头有一个模式,我假设您可以读取它,将其转换为Schema对象,然后将其传递给GenericDatumReader(模式)构造函数。 了解消息的序列化方式会很有趣。也许DataFileWriter用于写入byte []而不是实际文件,那么您可以使用DataFileReader来反序列化数据吗?

答案 1 :(得分:0)

  1. 添加Maven依赖项

    <dependency>
        <groupId>org.apache.avro</groupId>
        <artifactId>avro-maven-plugin</artifactId>
        <version>1.9.1</version>
        <type>maven-plugin</type>
    </dependency>
    
  2. 创建如下文件

     {"namespace": "tachyonis.space",
       "type": "record",
       "name": "Avro",
       "fields": [
          {"name": "Id", "type": "string"},
        ]
      }
    
  3. 在src / main / resources中另存为Avro.avsc。

  4. 在Eclipse或任何IDE Run中,> Maven生成源,这些源创建Avro.java来打包文件夹[namespace] tachyonis.space

    props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
    props.put(AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, SCHEMA_REGISTRY_URL_CONFIG);
    props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
    props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, KafkaAvroDeserializer.class);
    props.put(KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG, true); 
    KafkaConsumer<String, Avro> consumer = new KafkaConsumer<>(props);
    
  5. 使用者/生产者必须在同一台机器上运行。否则,您需要在Windows / Linux中配置主机文件,并将所有组件配置属性从localhost更改为映射到实际IP地址,以广播到生产者/消费者。否则,您会收到诸如网络连接问题之类的错误

    Connection to node -3 (/127.0.0.1:9092) could not be established. Broker may not be available