Apache kafka 我如何用嵌入的模式从卡夫卡反序列化Avro

Apache kafka 我如何用嵌入的模式从卡夫卡反序列化Avro,apache-kafka,apache-storm,avro,Apache Kafka,Apache Storm,Avro,我从卡夫卡主题接收二进制Avro文件,我必须反序列化它们。在卡夫卡收到的消息中,我可以在每条消息的开头看到一个模式。我知道不嵌入模式并将其与实际的Avro文件分离是一种更好的做法,但我无法控制生产者,也无法改变这一点 我的代码运行在Apache Storm之上。首先,我创建一个阅读器: mDatumReader = new GenericDatumReader<GenericRecord>(); 但是当一条消息到达时,我得到一个错误: Caused by: java.lang.Nu

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

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

mDatumReader = new GenericDatumReader<GenericRecord>();
但是当一条消息到达时,我得到一个错误:

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:?]
原因:java.lang.NullPointerException:writer不能为null!
在org.apache.avro.io.ResolvingDecoder.resolve(ResolvingDecoder.java:77)~[stormjar.jar:?]
在org.apache.avro.io.ResolvingDecoder.(ResolvingDecoder.java:46)~[stormjar.jar:?]
在org.apache.avro.io.DecoderFactory.resolvingDecoder(DecoderFactory.java:307)~[stormjar.jar:?]
在org.apache.avro.generic.GenericDatumReader.getResolver(GenericDatumReader.java:122)~[stormjar.jar:?]
在org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:137)~[stormjar.jar:?]
我看到的所有答案都是关于使用其他格式,更改传递给卡夫卡的消息或其他内容。我无法控制这些事情


我的问题是,给定一条在二进制消息中嵌入模式的
bytes[]
消息,如何在不声明模式的情况下反序列化该Avro文件,以便我可以读取它。

对于DatumReader/Writer,没有嵌入模式这样的东西。当我第一次看到阿夫罗和卡夫卡时,这也是我的误解。但是Avro序列化程序的源代码清楚地表明,在使用GenericDatumWriter时没有嵌入任何模式

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

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

  • 添加Maven依赖性

    <dependency>
        <groupId>org.apache.avro</groupId>
        <artifactId>avro-maven-plugin</artifactId>
        <version>1.9.1</version>
        <type>maven-plugin</type>
    </dependency>
    
  • 将上述内容另存为src/main/resources中的Avro.avsc

  • 在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);
    
  •  {"namespace": "tachyonis.space",
       "type": "record",
       "name": "Avro",
       "fields": [
          {"name": "Id", "type": "string"},
        ]
      }
    
    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);
    
    Connection to node -3 (/127.0.0.1:9092) could not be established. Broker may not be available