使用Apache Beam进行窗口化 - 修复Windows并不是要关闭?

时间:2017-05-16 21:23:14

标签: java google-cloud-dataflow apache-beam

我们正在尝试在Apache Beam管道上使用固定窗口(使用DirectRunner)。我们的流程如下:

  1. 从pub / sub
  2. 中提取数据
  3. 将JSON反序列化为Java对象
  4. 窗口事件w /固定窗口为5秒
  5. 使用自定义CombineFn,将Event的每个窗口合并为List<Event>
  6. 为了测试,只需输出结果List<Event>
  7. 管道代码:

        pipeline
                    // Read from pubsub topic to create unbounded PCollection
                    .apply(PubsubIO
                        .<String>read()
                        .topic(options.getTopic())
                        .withCoder(StringUtf8Coder.of())
                    )
    
                    // Deserialize JSON into Event object
                    .apply("ParseEvent", ParDo
                        .of(new ParseEventFn())
                    )
    
                    // Window events with a fixed window size of 5 seconds
                    .apply("Window", Window
                        .<Event>into(FixedWindows
                            .of(Duration.standardSeconds(5))
                        )
                    )
    
                    // Group events by window
                    .apply("CombineEvents", Combine
                        .globally(new CombineEventsFn())
                        .withoutDefaults()
                    )
    
                    // Log grouped events
                    .apply("LogEvent", ParDo
                        .of(new LogEventFn())
                    );
    

    我们看到的结果是最后一步从未运行过,因为我们没有得到任何记录。

    此外,我们在自定义System.out.println("***")课程的每个方法中添加了CombineFn,以便跟踪这些方法的运行时间,而且似乎他们也不会运行。

    这里窗口设置不正确吗?我们按照在https://beam.apache.org/documentation/programming-guide/#windowing找到的一个例子来看,这似乎相当简单,但显然有一些基本的缺失。

    感谢任何见解 - 提前感谢!

1 个答案:

答案 0 :(得分:9)

看起来主要问题确实是一个缺失的触发器 - 窗口打开了,没有什么可以告诉它什么时候发出结果。我们只想根据处理时间(而不是事件时间)进行窗口化,因此执行以下操作:

.apply("Window", Window
    .<Event>into(new GlobalWindows())
    .triggering(Repeatedly
        .forever(AfterProcessingTime
            .pastFirstElementInPane()
            .plusDelayOf(Duration.standardSeconds(5))
        )
    )
    .withAllowedLateness(Duration.ZERO).discardingFiredPanes()
)

本质上,这会创建一个全局窗口,触发在处理第一个元素5秒后发出事件。每次关闭窗口时,一旦窗口收到元素,另一个窗口就会打开。当我们没有withAllowedLateness篇时,梁抱怨了 - 据我所知,这只是告诉它忽略任何后期数据。

我的理解可能有点偏僻,但上面的片段已经解决了我们的问题!