簡體   English   中英

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

[英]How I deserialize Avro from Kafka with embedded schema

我從 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 文件,以便我可以讀取它。

使用 DatumReader/Writer,沒有像嵌入式模式這樣的東西。 也是我第一次看 Avro 和 Kafka 時的誤解。 但是 Avro Serializer 的源代碼清楚地表明使用 GenericDatumWriter 時沒有嵌入模式。

Data File Writer 在文件的開頭寫入模式,然后使用 GenericDatumWriter 添加 GenericRecords。

既然你一開始說有一個架構,我假設你可以閱讀它,把它變成一個 Schema 對象,然后將它傳遞給 GenericDatumReader(schema) 構造函數。 知道消息是如何序列化的會很有趣。 也許 DataFileWriter 用於寫入 byte[] 而不是實際文件,那么您可以使用 DataFileReader 反序列化數據?

  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 中運行 > 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 中配置 hosts 文件並將所有組件配置屬性從 localhost 更改為映射到實際 IP 地址以向生產者/消費者廣播。 否則會出現網絡連接問題等錯誤

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM