KafkaAvroSerializer用于在没有schema.registry.url的情况下序列化Avro

时间:2017-08-11 12:52:12

标签: java apache-kafka avro confluent-schema-registry

我是Kafka和Avro的菜鸟。所以我一直试图让Producer / Consumer运行起来。到目前为止,我已经能够使用以下内容生成和使用简单的字节和字符串: 制作人的配置:

    Properties props = new Properties();
    props.put("bootstrap.servers", "localhost:9092");
    props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
    props.put("value.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");

    Schema.Parser parser = new Schema.Parser();
    Schema schema = parser.parse(USER_SCHEMA);
    Injection<GenericRecord, byte[]> recordInjection = GenericAvroCodecs.toBinary(schema);

    KafkaProducer<String, byte[]> producer = new KafkaProducer<>(props);

    for (int i = 0; i < 1000; i++) {
        GenericData.Record avroRecord = new GenericData.Record(schema);
        avroRecord.put("str1", "Str 1-" + i);
        avroRecord.put("str2", "Str 2-" + i);
        avroRecord.put("int1", i);

        byte[] bytes = recordInjection.apply(avroRecord);

        ProducerRecord<String, byte[]> record = new ProducerRecord<>("mytopic", bytes);
        producer.send(record);
        Thread.sleep(250);
    }
    producer.close();
}

现在这一切都很好,当我尝试序列化POJO时问题就出现了。 因此,我能够使用Avro提供的实用程序从POJO获取AvroSchema。 硬编码架构,然后尝试创建通用记录以通过KafkaProducer发送 生产者现在设置为:

    Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.KafkaAvroSerializer");

Schema.Parser parser = new Schema.Parser();
Schema schema = parser.parse(USER_SCHEMA); // this is the Generated AvroSchema
KafkaProducer<String, byte[]> producer = new KafkaProducer<>(props);

这就是问题所在:我使用KafkaAvroSerializer的那一刻,生产商没有因为: 缺少必需参数:schema.registry.url

我读到了为什么需要这样做,以便我的消费者能够破译生产者发送给我的任何东西。 但是,AvroMessage中是否已嵌入了架构? 如果有人可以共享一个使用KafkaProducer和KafkaAvroSerializer的工作示例,而不必指定schema.registry.url

,那将会非常棒。

也非常感谢有关架构注册表实用程序的任何见解/资源。

谢谢!

5 个答案:

答案 0 :(得分:15)

首先注意:vanilla apache kafka中未提供KafkaAvroSerializer - 它由Confluent Platform提供。 (https://www.confluent.io/),作为其开源组件(http://docs.confluent.io/current/platform.html#confluent-schema-registry

的一部分

快速回答:不,如果您使用KafkaAvroSerializer,则需要一个架构注册表。在这里查看一些示例: http://docs.confluent.io/current/schema-registry/docs/serializer-formatter.html

架构注册表的基本思想是每个主题都将引用一个avro架构(即,您只能发送彼此一致的数据。但架构可以有多个版本,因此您仍需要识别每条记录的架构)

我们不想像你暗示的那样为每个数据编写模式 - 通常,模式比你的数据更大!每次阅读时都会浪费时间解析它,浪费资源(网络,磁盘,CPU)

相反,模式注册表实例将执行绑定avro schema <-> int schemaId,然后序列化程序将在从注册表获取数据之后仅在数据之前写入此ID(并将其缓存以供以后使用)。

所以在kafka中,你的记录将是[<id> <bytesavro>](由于技术原因而是魔术字节),这只是5字节的开销(与模式的大小比较) 在阅读时,您的消费者将找到与id相对应的模式,以及与之相关的反序列化avro字节。您可以在汇合文档中找到更多信息

如果您确实想要为每条记录编写架构,那么您将需要一个其他序列化程序(我认为编写自己的序列化程序,但它很容易,只需重用https://github.com/confluentinc/schema-registry/blob/master/avro-serializer/src/main/java/io/confluent/kafka/serializers/AbstractKafkaAvroSerializer.java并删除架构注册表部分用模式替换它,读取相同)。但是如果你使用avro,我真的会劝阻这个 - 一天之后,你需要实现类似avro注册表来管理版本控制

答案 1 :(得分:1)

正如其他人所指出的那样,KafkaAvroSerializer需要使用Schema Registry(它是Confluent平台的一部分),并且使用需要许可。

使用模式注册表的主要优点是,与为每条消息编写带有模式的二进制有效负载相比,在线上的字节数会减少。

我写了blog post详细介绍了优点

答案 2 :(得分:0)

虽然检查的答案都是正确的,但还应提及可以禁用模式注册

只需将auto.register.schemas设置为false

答案 3 :(得分:0)

您始终可以将值类设为手动实现Serialiser<T>Deserialiser<T>(对于Kafka Streams来说是Serde<T>)。 Java类通常是从Avro文件生成的,因此直接进行编辑不是一个好主意,但是包装可能是冗长但可行的方式。

另一种方法是调整用于Java类生成的Arvo生成器模板,并自动生成所有这些接口的实现。 Avro maven和gradle插件都支持自定义模板,因此应该易于配置。

我创建的https://github.com/artemyarulin/avro-kafka-deserializable更改了模板文件和可用于生成文件的简单CLI工具

答案 4 :(得分:0)

您可以创建自定义Avro序列化程序,然后即使没有Schema注册表,您也可以生成主题的记录。检查下面的文章。

https://codenotfound.com/spring-kafka-apache-avro-serializer-deserializer-example.html

这里他们使用了 Kafkatemplate 。我尝试使用

KafkaProducer<String, User> UserKafkaProducer

工作正常 但是,如果您想使用 KafkaAvroSerialiser ,则需要提供Schema RegistryURL