使用触发器限制窗口的最大长度

时间:2016-03-03 20:14:02

标签: java session google-cloud-platform google-cloud-dataflow

我想弄清楚如何限制会话的最大长度。在做触发的同时。我目前的触发器如下所示:

return AfterEach.inOrder(
                // speculatively trigger
                Repeatedly.forever(AfterProcessingTime.pastFirstElementInPane().plusDelayOf(earlyFiringInterval).orFinally(AfterWatermark.pastEndOfWindow())),
                // finally trigger for late
                Repeatedly.forever(AfterProcessingTime.pastFirstElementInPane().plusDelayOf(lateFiringInterval)));

这样可以正常触发每个earlyFiringInterval时间单位,直到水印通过窗口的末尾,然后触发每个lateFiringInterval时间单位。

不幸的是,会话可能会持续数天,这会导致窗口长时间保持打开并导致水印被隐藏。我正在尝试构建一个可以“切割”窗口的触发器,以便:

  • 任何会话都不能超过maxSessionLength时间(事件时间)。
  • 或者,将会话限制为窗格中的某些maxSessionLength个事件。 - 这在积累模式下有效。 (不理想)

所以,我有:

return AfterEach.inOrder(
                Repeatedly
                        // speculatively trigger at every 'earlyFiringInterval'
                        .forever(AfterProcessingTime.pastFirstElementInPane().plusDelayOf(earlyFiringInterval)
                        // terminate trigger when any of the following conditions are met:
                        //  * We have collected either 'maxEventCount' events in the pane
                        //  * Watermark has passed the window
                        .orFinally(AfterFirst.of(AfterPane.elementCountAtLeast(maxEventCount), AfterWatermark.pastEndOfWindow()))),
                Repeatedly
                        // trigger for late data at every 'lateFiringInterval'
                        .forever(AfterProcessingTime.pastFirstElementInPane().plusDelayOf(lateFiringInterval)))
                        .orFinally(AfterPane.elementCountAtLeast(maxEventCount));

我想知道这是否可行,或者是否有更好的方法来“限制窗口大小”。

1 个答案:

答案 0 :(得分:3)

您可以通过指定OutputTimeFn来保持水印的前进,同时保持会话的完全保真度:

Window.into(Sessions.withGapDuration(...))
      .withOutputTimeFn(OutputTimeFns.outputAtEndOfWindow())

就像CombineFn确定从分组转换中输出的一样(我们可以将GroupByKey视为通过连接组合),OutputTimeFn确定分组变换输出的时间戳

SDK提供了一些常见的选择:

  • OutputTimeFns.outputAtEndOfWindow()
  • OutputTimeFns.outputAtEarliestInputTimestamp()
  • OutputTimeFns.outputAtLatestInputTimestamp()

今天的默认值为outputAtEarliestInputTimestamp(),它允许您在下游生成的元素中应用的时间戳方面具有最大的灵活性,但不幸的是,在保留水印的(必要的)成本方面。

如果您不打算在窗口内的时间戳显式输出,选择outputAtEndOfWindow()可以让水印尽快前进。

注意 :此功能标记为Experimental。这意味着它的API可能会发生变化(例如,它可能仅限于几个固定常量,而不是接受任意OutputTimeFn实现。这个概念几乎肯定会保留,因为我们总是需要决定分组变换输出的时间戳。

如果您仍然希望因其他原因而减少会话,请发表评论,我会详细说明其他选项。

顺便说一句,我强烈推荐我们现在提供的简化触发器语法:

AfterWatermark.pastEndOfWindow()
    .withEarlyFirings(
        AfterProcessingTime.pastFirstElementInPane()
            .plusDelayOf(earlyFiringInterval))
    .withLateFirings(
        AfterProcessingTime.pastFirstElementInPane()
            .plusDelayOf(lateFiringInterval))