我是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
,那将会非常棒。也非常感谢有关架构注册表实用程序的任何见解/资源。
谢谢!
答案 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