如何在键控窗口上调试多个触发事件

时间:2019-08-21 16:46:14

标签: apache-flink

我的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时,该行为仍然存在。 我的问题是,这可能是由每个窗口上的多个触发事件引起的,还是有其他可能的解释?如何调试原因?

谢谢

1 个答案:

答案 0 :(得分:1)

水印在您工作中的作用是触发结账 滑动事件时间窗口为了扮演那个角色 正确地,它们应该基于事件中的时间戳, 比一些任意常数(9999L)大。同一对象的原因 负责提取时间戳并提供水印 以便该对象可以在其上创建的水印 对事件流中时间戳的观察。所以除非你 事件时间戳也基于增加类似的计数器, 这可以解释您所看到的某些行为。

另一个问题是,虽然对每个对象都调用extractTimestamp 事件,在定期水印分配器中,使用getCurrentWatermark方法 每200毫秒(默认)在单独的线程中调用一次。如果 您需要在每次活动后使用水印, AssignerWithPunctuatedWatermarks,尽管这样做有点 反模式(因为具有太多水印会增加开销)。

如果您的时间戳是完全人为的,则可能会发现一个 SlidingCountWindow更自然地适合您的工作。