如何从Apache Nifi的kafka主题中生成Avro消息,然后使用kafka流读取它?

时间:2018-10-09 12:00:25

标签: apache-kafka avro apache-nifi

我想使用apache nifi将一些通用数据生成kafka主题,并且我希望这些数据采用avro格式。 我为此做了什么:

  1. 在架构注册表中创建新架构:
  

{“ type”:“ record”,“ name”:“ my_schema”,“ namespace”:   “ my_namespace”,“ doc”:“”,“ fields”:[       {         “ name”:“键”,         “ type”:“ int”       },       {         “ name”:“ value”,         “类型”:[           “空值”,           “ int”         ]       },       {         “ name”:“ event_time”,         “ type”:“ long”       }]}

  1. 创建简单的nifi管道: enter image description here ConvertAvroSchema设置: enter image description here PublishKafkaRecord设置: enter image description here AvroReader设置: enter image description here AvroRecordSetWriter设置: enter image description here
  2. 然后我尝试使用kafka流阅读它:

    公共课程测试{     私人最终静态Logger logger = Logger.getLogger(KafkaFilterUsingCacheAvro.class);

    public static void main(String[] args) {
        Properties properties = new Properties();
    
        properties.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "broker:9092");
        properties.put(StreamsConfig.APPLICATION_ID_CONFIG, "app");
        properties.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());
        properties.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, GenericAvroSerde.class);
        properties.put(AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, "registry:8081");
    
        StreamsBuilder builder = new StreamsBuilder();
        KStream<String, GenericRecord> source = builder.stream("topic");
        source.foreach((k, v) -> logger.info(String.format("[%s]: %s", k, v.toString())));
    
        Topology topology = builder.build();
        KafkaStreams streams = new KafkaStreams(topology, properties);
        streams.start();
    }
    

    }

GenericAvroSerde-https://github.com/JohnReedLOL/kafka-streams/blob/master/src/main/java/io/confluent/examples/streams/utils/GenericAvroSerde.java

结果我得到了错误:

  

由以下原因引起:org.apache.kafka.common.errors.SerializationException:   反序列化ID -1的Avro消息时出错,原因是:   org.apache.kafka.common.errors.SerializationException:未知魔术   字节!

我还尝试在avroreader \ writer中显式设置avro模式,但这无济于事。另外,如果我尝试从主题中读取字节并将其转换为字符串表示形式,我将得到以下信息:

  

Objavro.schema {“ type”:“ record”,“ name”:“ my_schema”,“ namespace”:“ my_namespace”,“ doc”:“”,“ fields”:[{“ name”:“ key “,” type“:” int“},{” name“:” value“,” type“:[” null“,” int“]},{” name“:” event_time“,” type“:” long “}]}avro.codecsnappyÛ4ým[©q   ÃàG0ê¸ä»/}½{Û4ým[©qÃààG0

我该如何解决?

1 个答案:

答案 0 :(得分:3)

在PublishKafka处理器中,您的Avro编写器配置为“嵌入式Avro架构”的“架构写入策略”。这意味着写入Kafka的消息是标准的Avro消息,其中嵌入了完整的架构。

在用户端(Kafka流)上,它看起来像希望使用融合的模式注册表,在这种情况下,它不希望使用嵌入式Avro模式,而是希望使用特殊的字节序列指定模式ID,然后通过裸露的Avro消息。

假设您希望保持消费者的状态不变,那么在NiFi方面,您将需要将Avro编写器的“架构写入策略”更改为“融合架构注册表参考”。我认为这可能还需要您更改Avro阅读器,才能使用Confluent Schema Registry服务访问架构。

或者,也许有一种方法可以使Kafka Streams读取嵌入式模式,而不使用Confluent模式注册表,但是我以前没有使用过Kafka Streams,所以我不能说这是否可行。