我的DataStream源自自定义SourceFunction,该SourceFunction以确定的顺序发出WINDOW大小的字符串序列。 目的是基于EventTime在键控流上创建滑动窗口,以对累积的字符串进行处理。 要分配EventTime和水印,我将AssignerWithPeriodicWaterMarks附加到流中。 滑动窗口使用自定义ProcessWindowFunction处理。
env.setStreamTimeCharacteristic(EventTime)
val seqStream = env.addSource(Seqstream)
.assignTimestampsAndWatermarks(SeqTimeStampExtractor())
.keyBy(getEventtimeKey)
.window(SlidingEventTimeWindows.of(Time.milliseconds(windowSize), Time.milliseconds(slideSize)))
val result = seqStream.process(ProcessSeqWindow(target1))
我的AssignerWithPeriodicWaterMarks看起来像这样:
class FASTATimeStampExtractor : AssignerWithPeriodicWatermarks<FASTAstring> {
var waterMark = 9999L
override fun extractTimestamp(element: FASTAstring, previousElementTimestamp: Long): Long {
return element.f1
}
override fun getCurrentWatermark(): Watermark? {
waterMark += 1
return Watermark(waterMark)
}
}
换句话说,源发出的每个元素都应具有自己的EvenTime,并且应发出WaterMark,在该时间内不允许出现其他事件。 在调试器中单步执行该流,指示EventTime / Watremarks已按预期生成。
我期望在EventTime上应使用与时间窗口(例如10 ms)成比例的许多元素来调用ProcessSeqWindow.run()。但是,我观察到的是,run()被单个元素多次调用,并且相对于EventTime以任意顺序调用。 当我将并行度强制为1时,该行为仍然存在。 我的问题是,这可能是由每个窗口上的多个触发事件引起的,还是有其他可能的解释?如何调试原因?
谢谢
答案 0 :(得分:1)
水印在您工作中的作用是触发结账 滑动事件时间窗口为了扮演那个角色 正确地,它们应该基于事件中的时间戳, 比一些任意常数(9999L)大。同一对象的原因 负责提取时间戳并提供水印 以便该对象可以在其上创建的水印 对事件流中时间戳的观察。所以除非你 事件时间戳也基于增加类似的计数器, 这可以解释您所看到的某些行为。
另一个问题是,虽然对每个对象都调用extractTimestamp 事件,在定期水印分配器中,使用getCurrentWatermark方法 每200毫秒(默认)在单独的线程中调用一次。如果 您需要在每次活动后使用水印, AssignerWithPunctuatedWatermarks,尽管这样做有点 反模式(因为具有太多水印会增加开销)。
如果您的时间戳是完全人为的,则可能会发现一个 SlidingCountWindow更自然地适合您的工作。