Java 编写自定义卡夫卡序列化程序

Java 编写自定义卡夫卡序列化程序,java,scala,serialization,apache-kafka,Java,Scala,Serialization,Apache Kafka,我在Kafka消息中使用我自己的类,该消息有一系列字符串数据类型 因此,我无法使用卡夫卡库附带的默认序列化程序类或StringSerializer 我想我需要编写自己的序列化程序并将其提供给producer properties?EDIT 在较新的Kafka客户端中,实现序列化程序,而不是编码器 编写自定义序列化程序所需的内容包括: 使用为通用代码指定的对象实现编码器 需要提供VerifiableProperties构造函数 重写toBytes(…)方法,确保返回字节数组 将序列化程序类

我在Kafka消息中使用我自己的类,该消息有一系列字符串数据类型

因此,我无法使用卡夫卡库附带的默认序列化程序类或
StringSerializer

我想我需要编写自己的序列化程序并将其提供给producer properties?

EDIT

在较新的Kafka客户端中,实现
序列化程序
,而不是
编码器


编写自定义序列化程序所需的内容包括:

  • 使用为通用代码指定的对象实现编码器
    • 需要提供
      VerifiableProperties
      构造函数
  • 重写
    toBytes(…)
    方法,确保返回字节数组
  • 将序列化程序类注入
    ProducerConfig
  • 为生产者声明自定义序列化程序 正如您在问题中提到的,Kafka提供了一种为制作人声明特定序列化程序的方法。序列化器类在
    ProducerConfig
    实例中设置,该实例用于构造所需的
    Producer

    如果您遵循,您将通过
    属性
    对象构造
    ProducerConfig
    。构建属性文件时,请确保包括:

    props.put("serializer.class", "path.to.your.CustomSerializer");
    
    在将消息附加到日志之前,使用希望Kafka用于序列化消息的类的路径

    创建Kafka理解的自定义序列化程序 编写Kafka能够正确解释的自定义序列化程序需要实现Kafka提供的
    Encoder[T]
    scala类,但以下方法在我的项目中用于序列化JSON:

    公共类JsonEncoder实现编码器{
    私有静态最终记录器Logger=Logger.getLogger(JsonEncoder.class);
    //实例化ObjectMapper很昂贵。在现实生活中,更喜欢注入值。
    私有静态最终ObjectMapper ObjectMapper=新ObjectMapper();
    公共JSONECODER(可验证属性可验证属性){
    /*此构造函数必须存在才能成功编译*/
    }
    @凌驾
    公共字节[]到字节(对象){
    试一试{
    返回objectMapper.writeValueAsString(object.getBytes();
    }捕获(JsonProcessingException e){
    logger.error(String.format(“对象%s的Json处理失败”,object.getClass().getName()),e);
    }
    返回“.getBytes();
    }
    }
    
    您的问题听起来像是在对附加到日志中的所有消息使用一个对象(我们称之为
    CustomMessage
    )。如果是这种情况,您的序列化程序可能更像这样:

    package com.project.serializer;
        
    public class CustomMessageEncoder implements Encoder<CustomMessage> {
        public CustomMessageEncoder(VerifiableProperties verifiableProperties) {
            /* This constructor must be present for successful compile. */
        }
    
        @Override
        public byte[] toBytes(CustomMessage customMessage) {
            return customMessage.toBytes();
        }
    }
    
    props.put("serializer.class", "path.to.your.CustomSerializer");
    

    您需要同时实现编码和解码器

    public class JsonEncoder implements Encoder<Object> {
            private static final Logger LOGGER = Logger.getLogger(JsonEncoder.class);
    
            public JsonEncoder(VerifiableProperties verifiableProperties) {
                /* This constructor must be present for successful compile. */
            }
    
            @Override
            public byte[] toBytes(Object object) {
                ObjectMapper objectMapper = new ObjectMapper();
                try {
                    return objectMapper.writeValueAsString(object).getBytes();
                } catch (JsonProcessingException e) {
                    LOGGER.error(String.format("Json processing failed for object: %s", object.getClass().getName()), e);
                }
                return "".getBytes();
            }
        }
    
    编写器和读取器代码如下

    byte[] bytes = encoder.toBytes(map);
            KeyedMessage<String, byte[]> message =new KeyedMessage<String, byte[]>(this.topic, bytes);
    
    JsonDecoder decoder = new JsonDecoder(null);
    Map map = (Map) decoder.fromBytes(it.next().message());
    
    byte[]bytes=encoder.toBytes(map);
    KeyedMessage message=新的KeyedMessage(this.topic,字节);
    JsonDecoder decoder=新JsonDecoder(空);
    Map Map=(Map)decoder.fromBytes(it.next().message());
    
    因此,我无法使用Kafka库附带的默认序列化程序类或StringSerializer

    当然可以

    例如,使用Jackson或Gson;将实例转换为JSON字符串,然后使用其中一个内置Kafka序列化程序

    其他选择 推荐

    将Avro或Protobuf序列化程序的合流版本与类的模式注册表一起使用



    如果将类写入
    ObjectOutputStream
    ,也可以使用
    ByteArraySerializer
    (但是,由于不支持跨语言,因此不建议这样做)

    事实上,这是Kafka的自定义编码器。可以在i7上运行Kafka应用程序吗?感谢这个Sam B。非常有用。既然我们已经序列化了对象,您如何在Kafka consumer中反序列化字节数组?一个建议是:由于构建
    ObjectMapper
    是一项繁重的操作,由于它们在构造之后是线程安全的,所以为编码器/解码器创建一个静态的最终实例是有意义的。否则构造将比实际读/写时间长10倍。@StaxMan说得对。我确信对于大多数应用程序来说,最好的方法是注入
    ObjectMapper
    ,但正如您所说,对于这个示例,显示单个实例化是一种改进。@SamB。是的,在许多情况下,注入正确配置的实例是有意义的。我只是想提到这一点,因为性能影响非常显著,而且代码经常被逐字剪切粘贴。如何创建编码器实例?可验证属性可以为空?
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.4.1.3</version>
    </dependency>
    
    properties.put("serializer.class","kafka.serializer.DefaultEncoder");
    
    byte[] bytes = encoder.toBytes(map);
            KeyedMessage<String, byte[]> message =new KeyedMessage<String, byte[]>(this.topic, bytes);
    
    JsonDecoder decoder = new JsonDecoder(null);
    Map map = (Map) decoder.fromBytes(it.next().message());