在flatMap之后对kafka Stream进行实体化



我想使用Spring Kafka支持的Kafka Streams来消费form two Kafka主题。Topics有不同的键和值。我想通过方法.merge(KStream<X,Y> otherStream)将第二个主题和merge中的键和值与第一个主题映射。

这里有一个例子:

// Block 1
KStream<MyKey, MyValue> stream2 = streamsBuilder.stream(
"second-topic",
consumedAs(OtherKey.class, OtherValue.class, AllowEmpty.NONE) // Provides default json Serde
).flatMap(
(key, value) -> {
List<KeyValue<MyKey, MyValue>> list = new ArrayList<>();
// Do stuff an fill out the list
return list;
});
// Block 2
KStream<MyKey, MyValue>[] branches = stream
.merge(stream2)
... business stuff

有了这个解决方案,我得到了一个ClassCastException,原因是MyKey不能转换为MyKey。原因是,它们是由不同的模块和类加载器提供的。该错误发生在序列化中的合并块中。使用transform(..)时,我也有同样的行为。如果我附加命令.through("tmp-topic"),一切都会正常工作。它认为主题的物化返回一个有效的可序列化对象,而不是flatMap(...)

我在groupByKey中找到了以下API文档:

。。。如果在该操作之前使用了密钥更改运算符(例如,selectKey(KeyValueMapper(、map(KeyValueMapper(、flatMap(KeyValueMap(或transform(TransformerSupplier,String…((,并且之后没有发生数据重分发(例如,通过(String((,则将在Kafka中创建内部重新分区主题。此主题将命名为"${applicationId}-XXX-repartition",其中"applicationId"是用户通过参数APPLICATION_ID_CONFIG在StreamsConfig中指定的,"XXX"是内部生成的名称,"-repartition"是固定后缀。您可以通过Topology.describe((检索所有生成的内部主题名称。在这种情况下,该流的所有数据都将通过重新分区主题进行重新分配,方法是将所有记录写入该主题,然后从中重新读取所有记录,从而使生成的KGroupdStream在其密钥上正确分区。。。

正如您所看到的,在更改像flatMap(...)这样的操作之后,最好的做法是将其写入一个主题,因为这是序列化和重新分区的缘故。

你认为使用through("topic")使其工作如何?有人知道吗,在flatMap(...)之后,是否有可能在不写主题的情况下实现?

版本
Spring Kafka版本:2.2.5.发布
Apache Kafka客户端:2.0.1
Apache Kavka流:2.0.1

仅在某些上下文中,每当您使用密钥更改操作时,任何使用新密钥的下游处理器都会触发重新分区主题的创建。重新分区主题确保新密钥位于正确的分区上。我知道你可能已经知道了,但为了清楚起见,我只是在这里重申这一点。

考虑到这一点,在修改密钥后执行through()操作是完全可以接受的,因为Kafka Streams无论如何都会这样做。

因此,拥有flatMap(...).through(someTopic)效果良好。

此外,通过这样做,还可以防止在下游的其他操作(联接、聚合(中重复使用具有修改键的KStream实例时发生多个重新分区的可能性。

HTH,

票据

最新更新