这是我们的设置,我们有一个主题,本主题有两个订阅v1和v2具有完全相同的设置,都是拉订阅,10秒确认截止日期。
订阅v1和v2都分离到专用数据流,其中v2的数据流更加优化,但几乎做同样的事情。
问题是我们时不时会看到下面的警告消息和积压开始只在v2订阅中生成,而v1显示很少甚至没有积压。
08:53:56.000 ${MESSAGE_ID} Pubsub processing delay was high at 72 sec.
v2中的数据流日志除上述消息外没有显示任何明显的信息。实际上v2数据流的CPU使用率低于v1,所以我无法理解这一点。
问题:
更新于2017/01/17
正如通过@ben所建议的那样,我们在PubSub读取之后立即执行的ParDo过滤操作似乎达到了意外的高延迟。但考虑到getClassroomIds
是一个简单的java列表,我不确定如何解决这个问题。一个问题是我们已经应用于pubsub懒惰的编码器?在调用ProcessContext#element()
时,我们在编码器中定义了解压缩和反序列化吗?
def processElement(c: DoFn[Entity, Entity]#ProcessContext) = {
val startTime = System.currentTimeMillis()
val entity = c.element()
if (!entity.getClassroomIds.isEmpty) {
c.output(entity)
}
val latencyMs = System.currentTimeMillis() - startTime
if (latencyMs > 1000) {
// We see this warning messages during the load spike
log.warn(s"latency breached 1 second threshold: $latencyMs ms")
}
}
答案 0 :(得分:1)
您提到的时间并不能准确地说明在该步骤中花费的时间。特别是,由于fusion optimization它反映了过滤操作后的所有ParDo
。
如果您的管道看起来像:
ReadFromPubSub - > ParDo(过滤器) - > ParDo(昂贵) - >帕尔(写)
在Expensive
的调用返回之前,Write
和Filter
都会对来自c.output
的每个元素执行。这是一个问题,因为它融入了PubSub中的元素。
最简单的解决方案可能是执行Reshuffle:
pipeline
.apply(PubSubIO.read(...))
.apply(keyEachElement by their value and Void)
.apply(new Reshuffle<E, Void>())
.apply(move the key back to the element)
// rest of the pipeline
请注意,使用Reshuffle
代替常规GroupByKey
具有不错的属性,因为它触发的速度比任何正常触发都要快。