如何调试我的 Dataflow 作业卡住的原因?

How can I debug why my Dataflow job is stuck?

我的数据流作业没有取得进展 - 或者进展非常缓慢,我不知道为什么。我怎样才能开始调查作业缓慢/卡住的原因?

您应该检查的第一个资源是 Dataflow 文档。检查这些应该有用:

如果这些资源没有帮助,我将尝试总结您的作业可能被卡住的一些原因,以及如何调试它。我将根据导致问题的系统部分来区分这些问题。您的工作可能是:


作业在启动时卡住

Dataflow 服务接收作业或启动新的 Dataflow worker 时,作业可能会卡住。一些风险因素是:

  • 您是否添加了自定义 setup.py 文件?
  • 您是否有任何需要在 worker 启动时进行特殊设置的依赖项?
  • 你在操纵工人容器吗?

调试这类问题 我通常打开 StackDriver 日志记录,并查找 worker-startup 日志(见下图)。这些日志由 worker 在使用您的代码和依赖项启动 docker 容器时写入。如果您在此处看到任何问题,则表明您的 setup.py、作业提交、暂存工件等存在问题。

您可以做的另一件事是保持相同的设置,运行 一个非常小的管道来暂存所有内容:

with beam.Pipeline(...) as p:
  (p 
   | beam.Create(['test element']) 
   | beam.Map(lambda x: logging.info(x)))

如果您没有在 StackDriver 中看到您的日志,那么您可以继续调试您的设置。 如果您确实在 StackDriver 中看到了日志,那么您的作业可能卡在了其他地方。


作业似乎卡在用户代码中

可能发生的其他事情是您的作业正在用户代码中执行某些操作卡住或缓慢。一些风险因素是:

  • 您的工作是否执行需要您等待的操作? (例如加载数据到外部服务,等待promises/futures)
    • 请注意,Beam 的一些内置转换正是这样做的(例如 Beam IOs,如 BigQueryIO、FileIO 等)。
  • 您的工作是否将非常大的侧输入加载到内存中?如果您使用 View.AsList 作为辅助输入,则可能会发生这种情况。
  • 您的作业是否在 GroupByKey 操作后加载非常大的可迭代对象?

此类问题的症状 可能是管道的吞吐量低于您的预期。 另一个症状 是在日志中看到以下行:

Processing stuck in step <STEP_NAME>/<...>/<...> for at least <TIME> without outputting or completing in state <STATE>
    .... <a stacktrace> ....

在这种情况下,查看流水线中哪个步骤消耗的时间最多并检查该步骤的代码以查看可能是什么问题是有意义的。

一些提示:

  • 非常大的侧输入可能很麻烦,因此如果您的管道依赖于访问非常大的侧输入,您可能需要重新设计它以避免瓶颈。

  • 可以对外部服务发出异步请求,但我建议您提交/完成 startBundlefinishBundle 调用的工作。

  • 如果您的管道的吞吐量不是您通常期望的,可能是因为您没有足够的并行度。这可以通过 Reshuffle 或通过将现有键分片为子键来解决(Beam 通常按键进行处理,因此如果键太少,并行度会很低)- 或使用 Combiner 而不是 GroupByKey + ParDo.

  • 您的吞吐量低的另一个原因可能是您的作业在外部调用上等待的时间太长。您可以尝试通过尝试批处理策略或异步 IO 来解决此问题。

一般来说,没有提高管道吞吐量的灵丹妙药,您需要进行试验。


数据新鲜度或系统延迟增加

首先,我建议您查看 this presentation on watermarks

对于流式传输,水印的推进是推动管道取得进展的动力,因此,重要的是要注意可能导致水印被阻止的事情,并使下游的管道停滞。水印可能卡住的一些原因:

  • 一种可能是您的管道遇到无法解决的错误情况。 当捆绑包处理失败时,您的管道将继续尝试无限期地执行该捆绑包,这将阻止水印。
    • 发生这种情况时,您会在 Dataflow 控制台中看到错误,并且随着重试捆绑包,计数会不断攀升。参见:

  • 将时间戳与数据相关联时,您可能会遇到错误。请确保您的时间戳数据的分辨率是正确的!
  • 虽然不太可能,但您可能遇到了 Dataflow 中的错误。如果其他提示都没有帮助,请打开支持票。