我正在尝试测试作为最后一个节点具有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,Produced
,Consumed
等都是默认值,可以正确找到)
我的测试包括以同步且无暂停的方式向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的行为是否有所改变?也许现在我必须设置新的设置来控制事件的发出?
答案 0 :(得分:3)
在Kafka 2.2中,引入了优化以减少Kafka Streams的资源占用。如果KTable
不需要进行计算,则不一定要实现。这适用于您的情况,因为mapValues()
可以即时计算。因为KTable
没有实现,所以没有缓存,因此每个输入记录都会产生一个输出记录。
比较:https://issues.apache.org/jira/browse/KAFKA-6036
如果要强制执行KTable
,可以将Materilized.as("someStoreName")
传递到StreamsBuilder#table()
方法中。