Apache kafka KafkaStreams如何在流聚合中指定SERDE?

Apache kafka KafkaStreams如何在流聚合中指定SERDE?,apache-kafka,apache-kafka-streams,Apache Kafka,Apache Kafka Streams,我正在开发一个Kafka streams应用程序,在弄清楚如何使聚合工作时遇到了一些困难 我有一个KStreambankTransactions,其中键的类型为String,值的类型为JsonNode,因此我用 // Definition of the different Serdes used in the streams final Serde<String> stringSerde = Serdes.String(); final Serde<JsonNode> j

我正在开发一个Kafka streams应用程序,在弄清楚如何使聚合工作时遇到了一些困难

我有一个KStream
bankTransactions
,其中键的类型为
String
,值的类型为
JsonNode
,因此我用

// Definition of the different Serdes used in the streams
final Serde<String> stringSerde = Serdes.String();
final Serde<JsonNode> jsonSerde = new JsonSerde();
final Serde<Long> longSerde = Serdes.Long();

config.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, stringSerde.getClass().getName());
config.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, jsonSerde.getClass().getName());
我在运行时遇到以下错误:

Caused by: org.apache.kafka.streams.errors.StreamsException:
A serializer (value: org.apache.kafka.connect.json.JsonSerializer) is not compatible to
the actual value type (value type: java.lang.Long).
Change the default Serdes in StreamConfig or provide correct Serdes via method parameters.
我知道Kafka在抱怨,因为我试图使用默认的Json serdes来序列化
Long
。所以我试着读了这个

KTable<String, Long> totalBalances = bankTransactions
        .groupByKey()
        .aggregate(
                () -> 0L,
                (key, transaction, balance) -> (Long)((Long)balance + transaction.get("amount").asLong()),
                Materialized.as("bank-total-balance").withValueSerde(Serdes.Long())
        );
KTable totalBalances=银行交易
.groupByKey()
.合计(
()->0升,
(键,事务,余额)->(长)((长)余额+事务.get(“金额”).asLong()),
物化的.as(“银行总余额”).withValueSerde(Serdes.Long())
);
但我在编译时遇到了一个错误:

Error:(121, 89) java: incompatible types:
org.apache.kafka.common.serialization.Serde<java.lang.Long> cannot be converted
to org.apache.kafka.common.serialization.Serde<java.lang.Object>
错误:(121,89)java:不兼容的类型:
无法转换org.apache.kafka.common.serialization.Serde
转到org.apache.kafka.common.serialization.Serde
我尝试了不同的方法来编写此代码(例如,使用
Serdes.long()
而不是我的
longerdes
,尝试参数化
物化的类型
,甚至尝试将我的初始值设定项和聚合器编写为函数,Java 7风格),但我无法找出我做错了什么


因此,我的问题很简单:如果不是默认的Serdes,如何正确指定聚合应使用的Serdes?

正确的语法如下:

KTable<String, Long> totalBalances = bankTransactions
        .groupByKey()
        .aggregate(
                () -> 0L,
                (key, transaction, balance) -> (Long)((Long)balance + transaction.get("amount").asLong()),
                Materialized.<String, Long, KeyValueStore<Bytes, byte[]>>as("bank-total-balances")
                        .withKeySerde(stringSerde)
                        .withValueSerde(longSerde)
        );
KTable totalBalances=银行交易
.groupByKey()
.合计(
()->0升,
(键,事务,余额)->(长)((长)余额+事务.get(“金额”).asLong()),
具体化。作为(“银行总余额”)
.withKeySerde(stringSerde)
.带ValueSerde(longSerde)
);
物化。
之后的三种类型是键、值和用于物化KTable的存储区的类型,此类型不应更改。然后,我们可以定义用于写入该键值存储的serde


注意我从github上的一个随机报告中得到了这个语法,我仍然乐意接受一个有一些文档支持的更精确的答案。

使用Java8,您不需要指定泛型类型。在Java7中,如果值的类型为unknown and Object,则案例失败。这不是卡夫卡团队特有的,而是一些Java魔法。查看示例repo和Java7示例:@MatthiasJ.Sax感谢您指出这一点,我将查看示例我认为(正如@MatthiasJ.Sax所说),代码可以这样编写:'Materialized.as(“银行总余额”)。with(stringSerde,longerde)'。因此,不再需要泛型。@克劳迪奥塔索我不再与卡夫卡合作,也没有时间更新更为最新的答案,但请随意添加另一个答案(或者编辑我的答案,如果你不太麻烦的话),你是我的英雄!
KTable<String, Long> totalBalances = bankTransactions
        .groupByKey()
        .aggregate(
                () -> 0L,
                (key, transaction, balance) -> (Long)((Long)balance + transaction.get("amount").asLong()),
                Materialized.<String, Long, KeyValueStore<Bytes, byte[]>>as("bank-total-balances")
                        .withKeySerde(stringSerde)
                        .withValueSerde(longSerde)
        );