我从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文件,以便我可以阅读它。
答案 0 :(得分:2)
使用DatumReader / Writer,没有像嵌入式架构那样的东西。看着Avro&amp; amp;是我的误会卡夫卡也是第一次。但是Avro Serializer的源代码清楚地表明在使用GenericDatumWriter时没有嵌入模式。
数据文件编写器在文件开头编写架构,然后使用GenericDatumWriter添加GenericRecords。
由于您说开头有一个模式,我假设您可以读取它,将其转换为Schema对象,然后将其传递给GenericDatumReader(模式)构造函数。 了解消息的序列化方式会很有趣。也许DataFileWriter用于写入byte []而不是实际文件,那么您可以使用DataFileReader来反序列化数据吗?
答案 1 :(得分:0)
添加Maven依赖项
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.9.1</version>
<type>maven-plugin</type>
</dependency>
创建如下文件
{"namespace": "tachyonis.space",
"type": "record",
"name": "Avro",
"fields": [
{"name": "Id", "type": "string"},
]
}
在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);
使用者/生产者必须在同一台机器上运行。否则,您需要在Windows / Linux中配置主机文件,并将所有组件配置属性从localhost更改为映射到实际IP地址,以广播到生产者/消费者。否则,您会收到诸如网络连接问题之类的错误
Connection to node -3 (/127.0.0.1:9092) could not be established. Broker may not be available