我们正在尝试在Apache Beam管道上使用固定窗口(使用DirectRunner
)。我们的流程如下:
CombineFn
,将Event
的每个窗口合并为List<Event>
List<Event>
管道代码:
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找到的一个例子来看,这似乎相当简单,但显然有一些基本的缺失。
感谢任何见解 - 提前感谢!
答案 0 :(得分:9)
看起来主要问题确实是一个缺失的触发器 - 窗口打开了,没有什么可以告诉它什么时候发出结果。我们只想根据处理时间(而不是事件时间)进行窗口化,因此执行以下操作:
.apply("Window", Window
.<Event>into(new GlobalWindows())
.triggering(Repeatedly
.forever(AfterProcessingTime
.pastFirstElementInPane()
.plusDelayOf(Duration.standardSeconds(5))
)
)
.withAllowedLateness(Duration.ZERO).discardingFiredPanes()
)
本质上,这会创建一个全局窗口,触发在处理第一个元素5秒后发出事件。每次关闭窗口时,一旦窗口收到元素,另一个窗口就会打开。当我们没有withAllowedLateness
篇时,梁抱怨了 - 据我所知,这只是告诉它忽略任何后期数据。
我的理解可能有点偏僻,但上面的片段已经解决了我们的问题!