【问题标题】:Deserializing Java objects from Kafka consumer从 Kafka 消费者反序列化 Java 对象
【发布时间】:2016-08-15 10:41:03
【问题描述】:

我有一个 Kafka 消费者,目前配置有:

kafkaProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
kafkaProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());

但我真正想要的是能够使用 Kryo Deserializer:

public class KryoPOJODeserializer<T> implements Deserializer<T> {

    private Kryo kryo = new Kryo();

    @Override
    public void configure(Map props, boolean isKey) {
        kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
        kryo.register( Arrays.asList( "" ).getClass(), new ArraysAsListSerializer() );
    }

    @Override
    public T deserialize(String topic, byte[] data) {
        // Deserialize the serialized object.
        return kryo.readObject(new Input(data), T.class);
    }

    @Override
    public void close() {

    }

}

我想不通的是,是否可以为不同的主题重用相同的消费者(每个主题上都有不同类型的 POJO)?如果我的消费者配置是:

kafkaProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, KryoPOJODeserializer.class.getName());

或者,我是否必须为每个主题设置一个单独的消费者?

或者,我是否必须删除反序列化器的泛型部分,始终返回一个对象,并将该对象转换为客户端代码中的相关 POJO?比如:

public class KryoPOJODeserializer implements Deserializer {

    private Kryo kryo = new Kryo();

    @Override
    public void configure(Map props, boolean isKey) {
        kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
        kryo.register( Arrays.asList( "" ).getClass(), new ArraysAsListSerializer() );
    }

    @Override
    public Object deserialize(String topic, byte[] data) {
        // Deserialize the serialized object.
        return kryo.readClassAndObject(new Input(new ByteArrayInputStream(data)));
    }

    @Override
    public void close() {

    }

}

后者可以,但感觉有点脏。

任何建议表示赞赏!

【问题讨论】:

    标签: java apache-kafka kryo


    【解决方案1】:

    您可以通过将Deserializer 实例直接传递给消费者来使用您原来的方法:

    KafkaConsumer<String, Foo> consumer = new KafkaConsumer<>(properties,
        new StringDeserializer(), new KryoPOJODeserializer(Foo.class));
    

    如果您想为多个主题重用相同的传入数据类型,那么您可以使用单个消费者设置对这些主题的订阅。如果您想要不同的对象类型的值,那么您将需要使用多个消费者。

    否则你的第二种方法也是有效的。

    【讨论】:

    • 所以我猜(最坏的情况)拥有与 Kafka 主题一样多的“KafkaConsumer”消费者是可以接受的吗?在我的脑海中,KafkaConsumer 是相当重量级的,类似于 Hibernate SessionFactory。如果不是这样,那会让生活变得更轻松!
    • 是的,这是可以接受的——消费者(不管消息传递技术如何)通常被编写为处理一种特定的有效负载类型,尽管总是有例外。至于 KafkaConsumer 是否“重”,这取决于您的意思。消费者将维护与其正在消费消息的所有代理的 TCP 连接。除此之外,没有线程池在后台做事。
    猜你喜欢
    • 2018-12-08
    • 2019-08-30
    • 1970-01-01
    • 2019-04-29
    • 2019-05-11
    • 2017-03-06
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    相关资源
    最近更新 更多