KTable应该发出的事件

时间:2019-04-15 10:23:15

标签: scala apache-kafka apache-kafka-streams

我正在尝试测试作为最后一个节点具有KTable的拓扑。我的测试使用的是成熟的Kafka集群(通过融合的Docker映像),所以我使用TopologyTestDriver

我的拓扑具有键值类型String -> Customer的输入和String -> CustomerMapped的输出。 Serdes,模式以及与Schema Registry的集成均按预期工作。

我正在使用Scala,Kafka 2.2.0,Confluent Platform 5.2.1和kafka-streams-scala。我的拓扑尽可能简化,如下所示:

val otherBuilder = new StreamsBuilder()

otherBuilder
     .table[String,Customer](source)
     .mapValues(c => CustomerMapped(c.surname, c.age))
     .toStream.to(target)   

(所有隐式Serdes,ProducedConsumed等都是默认值,可以正确找到)

我的测试包括以同步且无暂停的方式向data主题发送一些记录(source)到target主题,然后从expected主题回读,我将结果与{ {1}}:

val data: Seq[(String, Customer)] = Vector(
   "key1" -> Customer(0, "Obsolete", "To be overridden", 0),
   "key1" -> Customer(0, "Obsolete2", "To be overridden2", 0),
   "key1" -> Customer(1, "Billy", "The Man", 32),
   "key2" -> Customer(2, "Tommy", "The Guy", 31),
   "key3" -> Customer(3, "Jenny", "The Lady", 40)
)
val expected = Vector(
   "key1" -> CustomerMapped("The Man", 32),
   "key2" -> CustomerMapped("The Guy", 31),
   "key3" -> CustomerMapped("The Lady", 40)
)

我构建了Kafka Stream应用程序,并在以下两个设置之间进行设置:

p.put(StreamsConfig.COMMIT_INTERVAL_MS_CONFIG, "5000")
val s: Long = 50L * 1024 * 1024
p.put(StreamsConfig.CACHE_MAX_BYTES_BUFFERING_CONFIG, s.toString)

因此,我希望KTable使用缓存,两次提交之间的间隔为5秒,缓存大小为50MB(对于我的方案来说足够了)。

我的问题是,我从target主题读回的结果始终包含key1的多个条目。我本来希望Obsolete和`Obsolete1的记录不会发出任何事件。实际输出为:

Vector(
    "key1" -> CustomerMapped("To be overridden", 0),
    "key1" -> CustomerMapped("To be overridden2", 0),
    "key1" -> CustomerMapped("The Man", 32),
    "key2" -> CustomerMapped("The Guy", 31),
    "key3" -> CustomerMapped("The Lady", 40)
)

最后一件事要提到:直到我将Kafka从2.1.0更新到2.2.0之前,该测试一直按预期进行。我再次验证了此应用程序降级的权限。

我很困惑,没有人能指出2.2.x版本中KTables的行为是否有所改变?也许现在我必须设置新的设置来控制事件的发出?

1 个答案:

答案 0 :(得分:3)

在Kafka 2.2中,引入了优化以减少Kafka Streams的资源占用。如果KTable不需要进行计算,则不一定要实现。这适用于您的情况,因为mapValues()可以即时计算。因为KTable没有实现,所以没有缓存,因此每个输入记录都会产生一个输出记录。

比较:https://issues.apache.org/jira/browse/KAFKA-6036

如果要强制执行KTable,可以将Materilized.as("someStoreName")传递到StreamsBuilder#table()方法中。