Apache Beam Java 2.26.0:BigQueryIO 'No rows present in the request'

Apache Beam Java 2.26.0: BigQueryIO 'No rows present in the request'

自从 Beam 2.26.0 更新后,我们 运行 在我们的 Java SDK 流数据管道中出现错误。我们已经调查这个问题很长一段时间了,但无法找到根本原因。降级到 2.25.0 时,管道按预期工作。

我们的管道负责摄取,即从 Pub/Sub 消耗并摄取到 BigQuery。具体来说,我们使用 PubSubIO 源和 BigQueryIO 接收器(流模式)。 运行管道时,遇到如下错误:

{
  "code" : 400,
  "errors" : [ {
    "domain" : "global",
    "message" : "No rows present in the request.",
    "reason" : "invalid"
  } ],
  "message" : "No rows present in the request.",
  "status" : "INVALID_ARGUMENT"
}

我们最初的猜测是管道的逻辑不知何故被窃听,导致 BigQueryIO 接收器失败。经过调查,我们得出结论,PCollection 馈送接收器确实包含正确的数据。

今天早些时候,我查看了 changelog 并注意到 BigQueryIO 接收器收到了大量更新。我特别担心以下变化:

  1. BigQuery 的 DATETIME 类型现在映射到 Beam 逻辑类型 org.apache.beam.sdk.schemas.logicaltypes.SqlTypes.DATETIME
  2. Java BigQuery 流式插入现在默认启用超时。传递 --HTTPWriteTimeout=0 以恢复旧行为

关于第一次更新,我确保在生成的 TableRow 对象中禁用所有 DATETIME。在这种特定情况下,错误仍然存​​在。

对于第二个更改,我不确定如何将 --HTTPWriteTimeout=0 标志传递给管道。如何最好地实现这一目标?

关于此问题的根本原因还有其他建议吗?

提前致谢!

--HTTPWriteTimeout 是一个 pipeline option。您可以像设置跑步者等一样设置它(通常在命令行上)。

我们终于能够解决这个问题,请放心,这是一段非常愉快的旅程。我们基本上调试了整个 BigQueryIO 连接器并得出以下结论:

  1. 转发到 BigQuery 的 TableRow 个对象用于包含枚举值。由于这些不可序列化,空负载被转发到 BigQuery。在我看来,这个错误应该更加明确(为什么突然改变了这个?)。

    • 通过向每个枚举条目 (com.google.api.client.util.Value) 添加 @value 注释解决了该问题。
  2. 同一个 TableRow 对象也包含 byte[] 类型的值。此值已注入 bytes 类型的 BigQuery 列中。虽然这在之前没有显式计算 base64 的情况下工作,但现在会产生错误。

    • 通过我们自己计算 base64 解决了这个问题(此设置也在下面 post 中讨论)。