首页 > 解决方案 > 为什么将 Avro 与 Kafka 一起使用 - 如何处理 POJO

问题描述

我有一个 spring 应用程序,它是我的 kafka 生产者,我想知道为什么 avro 是最好的方法。我阅读了它以及它所提供的所有内容,但是为什么我不能序列化我用杰克逊自己创建的 POJO 并将其发送到 kafka?

我这么说是因为 avro 的 POJO 生成并不是那么直接。最重要的是,它需要 maven 插件和 .avsc 文件。

因此,例如,我的 kafka 制作人有一个 POJO,我自己创建了一个名为 User:

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 用户并反序列化消息。是空间的问题吗?以这种方式序列化和反序列化也不是更快吗?更不用说维护模式注册表的开销了。

标签: javaapache-kafkaavroconfluent-schema-registry

解决方案


您不需要 AVSC,您可以使用 AVDL 文件,它基本上看起来与 POJO 相同,只有字段

@namespace("com.example.mycode.avro")
protocol ExampleProtocol {
   record User {
     long id;
     string name;
   }
}

哪个,当使用idl-protocolMaven 插件的目标时,将为您创建这个 AVSC,而不是您自己编写它。

{
  "type" : "record",
  "name" : "User",
  "namespace" : "com.example.mycode.avro",
  "fields" : [ {
    "name" : "id",
    "type" : "long"
  }, {
    "name" : "name",
    "type" : "string"
  } ]
}

它还会在您的类路径中放置一个SpecificDataPOJO User.java,以便在您的代码中使用。


如果您已经有 POJO,则不需要使用 AVSC 或 AVDL 文件。有一些库可以转换 POJO。例如,您可以使用 Jackson,它不仅适用于 JSON,您可能只需要JacksonAvroSerializer为 Kafka 创建一个,或者查找是否存在。

Avro 还具有基于反射的内置库


那么问题来了——为什么是 Avro(对于 Kafka)?

好吧,拥有架构是一件好事。想想 RDBMS 表,您可以解释该表,并且您会看到所有列。转移到 NoSQL 文档数据库,它们几乎可以包含任何内容,这就是 Kafka 的 JSON 世界。

假设您的 Kafka 集群中有消费者不知道主题中的内容,他们必须确切知道主题中产生了谁/什么。他们可以尝试控制台消费者,如果是像 JSON 这样的明文,那么他们必须找出他们感兴趣的一些字段,然后一次又一次地执行类似 HashMap 的片状.get("name")操作,只有在字段不存在时才会遇到 NPE不存在。使用 Avro,您可以清楚地定义默认值和可为空的字段。

不需要使用模式注册表,但它为explain topicRDBMS 类比提供了这种类型的语义。它还使您无需将模式与每条消息一起发送,以及 Kafka 主题的额外带宽费用。不过,注册表不仅对 Kafka 有用,因为它可以用于 Spark、Flink、Hive 等,用于围绕流数据摄取的所有数据科学分析。


假设您确实想使用 JSON,然后尝试改用 MsgPack,您可能会看到 Kafka 吞吐量增加并节省代理上的磁盘空间


您还可以使用其他格式,如 Uber 比较过的 Protobuf 或 Thrift


推荐阅读