我使用Scio编写了一个Apache Beam作业,目的是为输入数据记录生成会话ID,然后在将它们输出到BigQuery之前以某种方式丰富它们。这是代码:
val measurements = sc.customInput("ReadFromPubsub",
PubsubIO
.readMessagesWithAttributes()
.withTimestampAttribute("ts")
.fromSubscription(subscription)
)
measurements
.map(extractMeasurement).flatMap {
case Success(event) =>
Some(event)
case Failure(ex) =>
None
}
.timestampBy(_.timestamp)
.withSessionWindows(sessionGap, WindowOptions(
trigger = Repeatedly.forever(AfterWatermark.pastEndOfWindow()),
accumulationMode = AccumulationMode.DISCARDING_FIRED_PANES,
allowedLateness = Duration.standardDays(1),
timestampCombiner = TimestampCombiner.END_OF_WINDOW
))
.keyBy(_.clientID)
.groupByKey
.toWindowed
.map(assignSessionID)
.toSCollection.flatMap(_.results)
.map(enrich)
.saveAsTypedBigQuery(output, bigquery.WRITE_APPEND, bigquery.CREATE_NEVER)
我正在使用事件时间戳,这是ts
中属性键PubsubMessage
的值,作为我的timestamp属性。在窗口化数据之前,这与我在.timestampBy
中使用的时间戳完全相同。我期待的是,一旦水印超过sessionGap(默认为30分钟),输出触发器就会触发。
使用Dataflow runner和DirectRunner,即使我模拟时间间隔超过30分钟的数据,触发器也不会触发。在Dataflow UI中,我可以看到水印永远不会根据事件时间戳前进,而只会每隔一分钟前进,就像没有收到数据一样。
我已经验证了实际接收到的数据,因为执行窗口之前的转换。我也用around 10 records per second进行了测试,但也许这还不足以更新水印?我还设置了一个JobTest,在其中我获得了预期的输出,也向我发出了问题,即问题是基于时间戳/水印的。
我确信我错过了文档中的重要内容或在某处犯了一个愚蠢的错误,并希望有人能指出我正确的方向。
答案 0 :(得分:1)
将消息发布到pubsub时,如何生成写入消息的“ ts”属性的时间戳,以及如何对其进行编码?
如果我没记错的话,时间戳必须按照RFC3339规范进行编码,例如“ 2020-10-02T10:00:00-05:00”之类的内容
您可以尝试的另一种方法是暂时删除“ .withTimestampAttribute(“ ts”)“行,以便自动生成所使用的时间戳。然后验证您的水印是否在前进。如果是这样,则说明时间戳值(例如,可能不是您期望的值)或其编码存在问题。
最后,如果使用云数据流运行器,请查看作业状态页面。那应该向您显示数据水印的当前值。您可以检查它是否符合您的期望。
答案 1 :(得分:0)
您可以尝试将early and late firings添加到AfterWatermark.pastEndofWindows中,以查看水印是否已更新,并检查是否有任何迟到的数据。另外,您还可以找到有关触发器here的文档。