Google cloud dataflow 利用定制水槽中的工人

Google cloud dataflow 利用定制水槽中的工人,google-cloud-dataflow,Google Cloud Dataflow,我有一个自定义接收器,它将最终结果从管道发布到存储库 我正在从BigQuery和GCS获取此管道的输入 将为所有工作区中的每个工作区调用水槽中的自定义写入程序。自定义编写器将只收集要PSU的对象,并将其作为WriteResult的一部分返回。最后,我将这些记录合并到CustomWriteOperation.finalize()中,并将其推送到我的存储库中 这适用于较小的文件。但是,如果结果大于5 MB,我的存储库将不接受。此外,它将不接受每小时不超过20次写入 如果我通过worker推送结果,那

我有一个自定义接收器,它将最终结果从管道发布到存储库

我正在从BigQuery和GCS获取此管道的输入

将为所有工作区中的每个工作区调用水槽中的自定义写入程序。自定义编写器将只收集要PSU的对象,并将其作为WriteResult的一部分返回。最后,我将这些记录合并到CustomWriteOperation.finalize()中,并将其推送到我的存储库中

这适用于较小的文件。但是,如果结果大于5 MB,我的存储库将不接受。此外,它将不接受每小时不超过20次写入

如果我通过worker推送结果,那么将违反每天写入的限制。如果我在CustomWriteOperation.finalize()中写入它,那么它可能会违反大小限制,即5MB

当前的方法是在CustomWriteOperation.finalize()中分块写入。由于许多工人没有执行此操作,因此可能会导致我的工作延迟。如何在finalize()中使用worker,以及如何为特定作业(即写作业)指定管道中要使用的worker数


或者有更好的方法吗?

接收器API不明确允许调整捆绑包大小

一种解决方法可能是使用ParDo将记录分组到捆绑包中。例如,您可以使用DoFn为每个记录随机分配一个介于1,…,N之间的键。然后,您可以使用GroupByKey将记录分组到KV中。这将产生大小大致相同的N组

因此,调用Sink.Writer.write可以一次用同一个键写入所有记录,因为write是并行调用的,所以包将并行写入

但是,由于给定的KV对可以被多次处理或同时在多个worker中处理,因此需要实现某种机制来创建锁,以便只尝试写入每组记录一次


您还需要处理失败和重试。

因此,如果我理解正确,您有一个

  • 每小时接受的写入操作不超过X次(我想如果您尝试执行更多操作,您将从正在写入的API中得到一个错误),并且
  • 每个写入操作的大小不能大于Y(具有类似的错误报告)
这意味着不可能在1小时内写入超过X*Y的数据,因此我认为,如果您想写入超过X*Y的数据,您可能希望管道等待的时间超过1小时

Dataflow目前不提供强制执行这两个限制的内置支持,但是看起来您应该能够简单地通过随机指数回退进行重试,以绕过第一个限制(),并且只剩下确保单个写入不会太大

可以在自定义接收器中的Writer类中限制单个写入。您可以维护记录的缓冲区,并让write()添加到缓冲区中,如果缓冲区刚好低于允许的写入大小,则通过发出API调用(如前所述,使用指数后退)来刷新缓冲区,然后在close()中再刷新一次

通过这种方式,您将编写尽可能大但不更大的捆绑包,如果您添加重试逻辑,也将遵守限制


总的来说,这似乎很适合Sink API。

我正在与Sam合作解决这一问题,以下是我们的目标系统施加的实际限制:每个API调用100 GB,每天最多25个API调用

考虑到这些限制,带有回退逻辑的重试方法可能会导致上载需要很多天才能完成,因为我们无法控制工作人员的数量

另一种方法是利用FileBasedSink并行编写多个文件。写入所有这些文件后,finalize(或copyToOutputFiles)可以合并文件,直到总大小达到100 GB并推送到目标系统。通过这种方式,我们利用writer线程的并行化,并尊重目标系统的限制


对此有何想法?或者其他想法?

如果管道每小时产生超过100MB的数据,那么它的预期行为是什么?根据您描述的内容,如果不违反其中一项要求,就不可能编写任何内容。同样,如果某些编写失败,会发生什么情况?接收器将重试写操作,但这可能会超过配额。我刚才以5MB为例。实际上是10GB。我只是把它放在一个很简单的地方。有没有办法单独为sink job配置工人数量?您能理解我的问题吗?请帮助我们开始使用Google Dataflow鉴于当前的API,这种方法似乎最有希望。创建一个
DoFn