Java 使用数据流从多个PubSub主题流式传输到BigQuery时,消息卡在GBP中?

Java 使用数据流从多个PubSub主题流式传输到BigQuery时,消息卡在GBP中?,java,google-bigquery,google-cloud-dataflow,google-cloud-pubsub,apache-beam-io,Java,Google Bigquery,Google Cloud Dataflow,Google Cloud Pubsub,Apache Beam Io,我有一个Java数据流管道,包括以下部分: PubSub订阅者阅读多个主题 展平.p集合操作 从PubsubMessage到TableRow的转换 BigQuery编写器将所有数据写入动态表 当订阅列表中有多个PubSub主题要连接时,所有元素都会卡在BigQuery编写器内的改组操作中的GroupByKey操作中。在发送了几十条测试消息之后,我让它运行了几个小时,但是没有任何东西写入BigQuery 我发现了以下三种解决方法(每种方法都与其他方法不同) 在Pubsub订阅上添加“with

我有一个Java数据流管道,包括以下部分:

  • PubSub订阅者阅读多个主题
  • 展平.p集合操作
  • 从PubsubMessage到TableRow的转换
  • BigQuery编写器将所有数据写入动态表
当订阅列表中有多个PubSub主题要连接时,所有元素都会卡在BigQuery编写器内的改组操作中的GroupByKey操作中。在发送了几十条测试消息之后,我让它运行了几个小时,但是没有任何东西写入BigQuery

我发现了以下三种解决方法(每种方法都与其他方法不同)

  • 在Pubsub订阅上添加“withTimestampAttribute”调用。属性的名称根本不重要-它可以是传入消息上的任何现有或不存在的属性
  • 将PubSub订阅数减少到1
  • 删除中间的flatte.pCollections操作,创建多个单独的管道,执行完全相同的操作
这些消息不是故意加时间戳的——只使用PubsubMessage时间戳将它们写入BigQuery是完全可以接受的

甚至添加一个不存在的timestamp属性似乎也能解决这个问题,这也让我感到困惑。我调试了这个问题,以便在管道中打印出时间戳,在这两种情况下它们都是可比较的;当指定一个不存在的时间戳属性时,它似乎还是回到pubsub时间戳


是什么导致了这个问题?我如何解决它?对我来说,最可接受的解决方法是删除flatte.pCollections操作,因为它不会使代码严格复杂化,但我无法弄清楚它失败的原因。

是否对管道应用了窗口化?警告您不要在没有任何窗口或触发的情况下使用无界PCollection(如Pub/Sub):

如果未为无界PCollection设置非全局窗口函数或非默认触发器,并随后使用分组转换(如GroupByKey或Combine),则管道将在构造时生成错误,作业将失败


在您的情况下,管道在构造时不会失败,但消息会被卡在GroupByKey中,因为它正在等待窗口结束。尝试在BigQuery编写器之前添加一个窗口,看看这是否解决了问题。

谢谢!添加一个窗口确实解决了这个问题。我仍然不确定为什么在某些情况下有必要这样做(更具体地说:将多个主题合并成一个PCollection),而在其他情况下则没有必要这样做。我浏览了BigQuery.write操作的源代码,一直到重新洗牌操作。该操作在执行GroupBy操作之前专门设置自己的窗口,然后将原始窗口放回原处。看到这一点,我不明白为什么预先设置一个窗口就可以解决这个问题。我所指的链接是:它似乎以无限的延迟重新进入,设置为在每个元素上触发。然而,它似乎没有做到这一点。