Google cloud dataflow 从云存储(GCS)读/写时,云数据流运行非常慢

Google cloud dataflow 从云存储(GCS)读/写时,云数据流运行非常慢,google-cloud-dataflow,Google Cloud Dataflow,自从使用最新版本的云数据流(0.4.150414)以来,当从云存储(GCS)读取数据时,我们的作业运行非常慢。在使用10个虚拟机运行20分钟后,我们只能读取大约20条记录,而以前我们可以读取数百万条记录而没有问题 虽然没有向控制台报告任何错误,但它似乎处于挂起状态 我们收到一封电子邮件,通知我们最新的构建速度会慢一些,可以通过使用更多的虚拟机来应对,但我们在50个虚拟机上得到了类似的结果 以下是工作id供参考:2015-04-22_22_20_21-5463648738106751600 实例:

自从使用最新版本的云数据流(0.4.150414)以来,当从云存储(GCS)读取数据时,我们的作业运行非常慢。在使用10个虚拟机运行20分钟后,我们只能读取大约20条记录,而以前我们可以读取数百万条记录而没有问题

虽然没有向控制台报告任何错误,但它似乎处于挂起状态

我们收到一封电子邮件,通知我们最新的构建速度会慢一些,可以通过使用更多的虚拟机来应对,但我们在50个虚拟机上得到了类似的结果

以下是工作id供参考:2015-04-22_22_20_21-5463648738106751600

实例:n1-standard-2

地区:us-central1-a

您的工作似乎使用了a
DoFn的辅助输入。由于CloudDataflowSDK for Java处理端输入的方式最近发生了变化,您的性能问题很可能与此有关。我正在转载一个相关问题的答案


证据似乎表明,管道如何处理端输入存在问题。具体地说,对于主输入的每个元素,很可能会一次又一次地从BigQuery重新读取边输入。这与数据流工作人员使用的虚拟机类型的更改完全正交,如下所述

这与Dataflow SDK for Java版本0.3.150326中所做的更改密切相关。在该版本中,我们更改了side输入API以应用于每个窗口。调用
sideInput()
现在只返回与主输入元素窗口相对应的特定窗口中的值,而不是整个sideInput
PCollectionView
。因此,无法再从
DoFn
startBundle
finishBundle
调用
sideInput()
,因为该窗口尚未知

例如,以下代码段存在一个问题,该问题将导致重新读取每个输入元素的端输入

@Override
public void processElement(ProcessContext c) throws Exception {
  Iterable<String> uniqueIds = c.sideInput(iterableView);

  for (String item : uniqueIds) {
    [...]
  }

  c.output([...]);
}
@覆盖
public void processElement(ProcessContext c)引发异常{
Iterable uniqueid=c.sideInput(iterableView);
用于(字符串项:UniqueID){
[...]
}
c、 产出([…]);
}
通过在第一次调用
processElement
期间将侧面输入缓存到转换的
List
成员变量(假设它适合内存),并在后续调用中使用缓存的
List
而不是侧面输入,可以改进此代码

此解决方案应恢复您以前看到的性能,当时可以从
startBundle
调用侧输入。从长远来看,我们将致力于为端输入提供更好的缓存。(如果这无助于完全解决问题,请通过电子邮件联系我们并分享相关代码片段。)



另外,在2015年4月9日左右,云数据流服务的更新确实改变了数据流工作者使用的虚拟机的默认类型。具体来说,我们减少了每个工人的默认核心数量,因为我们的基准测试表明,对于典型的工作来说,它是经济高效的。这并不是任何类型的数据流服务的减速——默认情况下,它只是以较少的每个工作者的资源运行。用户仍然可以选择覆盖工人数量和工人使用的虚拟机类型。

我们也遇到了类似的问题。当side输入从一个BigQuery表读取数据流时,而不是大容量加载。当我们复制表格,并从副本中读取时,一切正常

如果您的表是流式的,请尝试复制它们并读取副本。这是一个解决办法


请参阅:

这绝对不是预期的行为。让我们澄清两件事:1)您是否能够通过常规的“gsutil”命令快速读取这些GCS文件?(只是为了确保这不是GCS问题)2)您是否可以尝试使用DirectPipelineRunner在较小的数据子集上运行管道,以检查它是否只发生在VM上,还是也发生在本地?您还可以尝试ssh到您的一个VM中,并查看它在做什么。一种方法是“ps aufx | grep java”定位数据流工作进程,“sudo kill-3$worker_PID”强制它将stacktrace转储到其stdout,“sudo docker ps”定位该进程运行的taskrunner容器(容器ID为左列),然后“sudo docker exec$CONTAINER_ID cat/dataflow/logs/taskrunner/harness/harness stdout.log”来打印其stdout,现在应该有堆栈跟踪。(对不起,我知道这很麻烦-我们正在改进调试体验)我可以使用gsutil读取bucket,也可以使用较小的数据集在本地运行它,没有任何问题。我现在将使用ssh连接到box上。嗨,Darren,你能通过ssh提取任何调试信息吗?这对我们解决问题非常有价值。我登录到一个VM并按照你的步骤操作,但目录/dataflow/logs不存在。