TopologyTestDriver在KTable聚合上发送不正确的消息

时间:2019-01-25 20:08:46

标签: apache-kafka apache-kafka-streams

我有一个聚合在KTable上的拓扑。 这是我创建的一种通用方法,用于根据我拥有的不同主题构建此拓扑。

public static <A, B, C> KTable<C, Set<B>> groupTable(KTable<A, B> table, Function<B, C> getKeyFunction,
        Serde<C> keySerde, Serde<B> valueSerde, Serde<Set<B>> aggregatedSerde) {
    return table
            .groupBy((key, value) -> KeyValue.pair(getKeyFunction.apply(value), value),
                    Serialized.with(keySerde, valueSerde))
            .aggregate(() -> new HashSet<>(), (key, newValue, agg) -> {
                agg.remove(newValue);
                agg.add(newValue);
                return agg;
            }, (key, oldValue, agg) -> {
                agg.remove(oldValue);
                return agg;
            }, Materialized.with(keySerde, aggregatedSerde));
}

这在使用Kafka时非常有效,但在通过`TopologyTestDriver`进行测试时则不能。

在两种情况下,当我得到更新时,首先调用subtractor,然后调用adder。问题在于,使用TopologyTestDriver时,会发出两条消息进行更新:一条消息在subtractor调用之后,另一条消息在adder调用之后。更不用说在subrtractor之后和adder之前发送的消息处于错误的阶段。

还有其他人可以确认这是一个错误吗?我已经针对Kafka 2.0.1版和2.1.0版进行了测试。

编辑:
我在github中创建了一个测试用例来说明问题:https://github.com/mulho/topology-testcase

1 个答案:

答案 0 :(得分:2)

预期的行为是有两个输出记录(一个“减”记录和一个“加”记录)。了解它的工作原理有些棘手,所以让我尝试解释一下。

假设您具有以下输入表:

 key |  value
-----+---------
  A  |  <10,2>
  B  |  <10,3>
  C  |  <11,4>

KTable#groupBy()上,提取值的第一部分作为新键(即1011),然后将第二部分相加(即234)中的聚合。由于AB记录都具有10作为新密钥,因此您将求和2+3,也将求和4作为新密钥11 。结果表将是:

 key |  value
-----+---------
  10 |  5
  11 |  4

现在假定更新记录<B,<11,5>>将原始输入KTable更改为:

 key |  value
-----+---------
  A  |  <10,2>
  B  |  <11,5>
  C  |  <11,4>

因此,新结果表应汇总5+4的{​​{1}}和11的{​​{1}}:

2

如果将第一个结果表与第二个结果表进行比较,您可能会注意到两个行都已更新。从10中减去旧的 key | value -----+--------- 10 | 2 11 | 9 记录,得到B|<10,3>,新的10|5记录被添加到10|2,从而得到B|<11,5>

这正是您看到的两个输出记录。第一个输出记录(执行减法后)更新第一行(它将减去不再属于聚合结果的旧值),而第二个记录将新值添加到聚合结果中。在我们的示例中,减记录为11|4,加记录为11|9(这些记录的格式为<10,<null,<10,3>>>(请注意,减记录仅设置了{{1} }部分,而添加记录仅设置<11,<<11,5>,null>>部分。

最后说明:不可能将正负记录放在一起,因为正负记录的键可以不同(在我们的示例<key, <plus,minus>>minus中),因此可能进入不同的分区。这意味着加号和减号操作可能由不同的机器执行,因此不可能只发出包含加号和减号部分的记录。