Java 为什么要将Avro与卡夫卡结合使用-如何处理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

我有一个spring应用程序,它是我的卡夫卡制作人,我想知道为什么avro是最好的方式。 我读过关于它和它所能提供的一切,但为什么我不能把我和杰克逊一起创作的POJO序列化,然后发送给卡夫卡呢

我这么说是因为来自avro的POJO一代人并不那么直截了当。 最重要的是,它需要maven插件和一个.avsc文件

例如,我的卡夫卡制作人创建了一个名为User的POJO:

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
POJO
User.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"
  } ]
}