Java 为什么要将Avro与卡夫卡结合使用-如何处理POJO
我有一个spring应用程序,它是我的卡夫卡制作人,我想知道为什么avro是最好的方式。 我读过关于它和它所能提供的一切,但为什么我不能把我和杰克逊一起创作的POJO序列化,然后发送给卡夫卡呢 我这么说是因为来自avro的POJO一代人并不那么直截了当。 最重要的是,它需要maven插件和一个.avsc文件 例如,我的卡夫卡制作人创建了一个名为User的POJO:Java 为什么要将Avro与卡夫卡结合使用-如何处理POJO,java,apache-kafka,avro,confluent-schema-registry,Java,Apache Kafka,Avro,Confluent Schema Registry,我有一个spring应用程序,它是我的卡夫卡制作人,我想知道为什么avro是最好的方式。 我读过关于它和它所能提供的一切,但为什么我不能把我和杰克逊一起创作的POJO序列化,然后发送给卡夫卡呢 我这么说是因为来自avro的POJO一代人并不那么直截了当。 最重要的是,它需要maven插件和一个.avsc文件 例如,我的卡夫卡制作人创建了一个名为User的POJO: public class User { private long userId; private Stri
public class User {
private long userId;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
}
我序列化它并将其发送到kafka中的用户主题。然后我有一个消费者,它本身有一个POJO用户,并对消息进行反序列化。
这是空间问题吗?以这种方式序列化和反序列化是否也更快?更不用说维护模式注册表的开销了。这是速度和存储的问题。序列化数据时,通常需要传输实际的模式,因此,这会导致有效负载大小的增加
Total Payload Size
+-----------------+--------------------------------------------------+
| Schema | Serialised Data |
+-----------------+--------------------------------------------------+
Schema Registry为模式和元数据提供了一个集中的存储库,以便在一个中央系统中注册所有模式。这种集中式系统使生产者能够只包含模式的ID,而不是完整的模式本身(文本格式)
因此,序列化变得更快
此外,schema registry versioning支持强制执行数据策略,这些策略可能有助于防止较新的架构破坏与现有版本的兼容性,从而可能导致停机或管道中的任何其他重大问题
Schema Registry的更多好处将在中详细解释 首先,卡夫卡不知道关键/价值内容。它操作字节,客户端(生产者/消费者)负责处理反序列化 到目前为止,最常见的选项似乎是JSON、protobuf和Avro 我个人对Avro的喜好以及我通常使用它并向他人推荐的原因: 1) 它是一个足够紧凑的二进制序列化,具有模式和逻辑类型(这有助于区分普通的
long
和时间戳(长毫秒)
)
2) Avro模式具有很强的描述性,并有完整的文档记录
3) 必须广泛支持大多数广泛使用的编程语言
4) Confluent(以及其他)为模式提供了一个存储库,即所谓的“模式注册表”,以便为您的模式提供一个集中存储。在Avro中,消息只包含模式版本ID,而不是模式本身
5) 如果您使用的是Java,那么从模式中生成POJO基类将带来巨大的好处
当然,您可以将其中的一部分与其他选项一起使用。您应该尝试并比较适合您的用例的所有选项
另外,我个人的意见是:如果不是字符串
,那就选择Avro。同时适用于键和值。您不需要AVSC,它基本上与POJO一样,只有字段
@namespace("com.example.mycode.avro")
protocol ExampleProtocol {
record User {
long id;
string name;
}
}
当使用Maven插件的idl协议
目标时,它将为您创建此AVSC,而不是您自己编写
{
"type" : "record",
"name" : "User",
"namespace" : "com.example.mycode.avro",
"fields" : [ {
"name" : "id",
"type" : "long"
}, {
"name" : "name",
"type" : "string"
} ]
}
它还将在类路径上放置一个SpecificData
POJOUser.java
,以便在代码中使用
如果您已经有了POJO,则不需要使用AVSC或AVDL文件。有一些库可以转换POJO。例如,您不仅需要JSON,还需要为卡夫卡创建一个
JacksonAvroSerializer
,或者查找是否存在
阿夫罗也有
那么问题是——为什么是阿夫罗(为卡夫卡) 嗯,有一个模式是一件好事。考虑一下RDBMS表,您可以解释该表,并且可以看到所有列。转到NoSQL文档数据库,它们可以包含任何内容,这就是Kafka的JSON世界 假设您的卡夫卡集群中有消费者不知道主题中有什么,他们必须确切知道主题中产生了谁/什么。他们可以尝试控制台使用者,如果它是一个类似JSON的纯文本,那么他们必须找出一些他们感兴趣的字段,然后反复执行类似
.get(“name”)
的散列映射操作,只有在字段不存在时才会遇到NPE。使用Avro,您可以清楚地定义默认值和可空字段
您不需要使用模式注册表,但它为RDBMS类比提供了这种类型的explain-topic
语义。它还使您无需将模式与每条消息一起发送,也无需在卡夫卡主题上花费额外的带宽。该注册表不仅对卡夫卡有用,因为它还可以用于Spark、Flink、Hive等所有围绕流式数据摄取的数据科学分析
假设您确实想使用JSON,那么您可能会看到Kafka吞吐量的增加,并在代理上节省磁盘空间
您也可以使用其他格式,如Protobuf或Thrift,是否有任何选项可以使用纯POJO和模式注册表,而不自动生成类?@wardziniak有Avro的
ReflectData
类,用于从POJO生成Avro。请注意,Java类型并不完全映射到Avro类型。例如,树状图和链接列表不能精确链接到Avro地图和列表,并且AvroMay中没有设置支持。该链接可以帮助您:
{
"type" : "record",
"name" : "User",
"namespace" : "com.example.mycode.avro",
"fields" : [ {
"name" : "id",
"type" : "long"
}, {
"name" : "name",
"type" : "string"
} ]
}