首页 > 解决方案 > 在 Cloud Dataflow 中限制对第三方的并发调用

问题描述

我正在研究一个需要将调用中的调用限制到第三方系统的管道,并考虑了几种不同的方法。

对于单个管道,我正在考虑使用无操作键控状态方法,这样并行性就限于键的数量。基本上,将其包含在相关阶段:

// Add a fake state entry to force serialization per-key.
@StateId("force-serialization")
private final StateSpec<ValueState<String>> myStateSpec = StateSpecs.value();

对于多个管道,我正在考虑使用二级租赁系统,我们尝试在其中申请租约startBundle(并将其归还finishBundle)。

最后一个问题是,在某些情况下,连续阶段会调用相同的服务,并且需要共享相同的飞行限制。我希望这与 fusion 很好地配合并且如果它们被融合,则不会有连续的阶段竞争相同的租约。例如,采取连续的阶段:

DoFn<KV<String, Foo>, KV<String, Bar>> Stage1  // Calls third party API
DoFn<KV<String, Bar>, KV<String, Baz>> Stage2  // Calls third party API

我在想我可以在 Foo 中包含一个在序列化时被删除的“sameBundle”标志。如果 Stage1 + Stage2 融合,那么这个标志将从 Stage1 传递到 Stage2,我可以假设它们将共享相同的飞行行为。如果不是,则标志将不会通过,因此两个阶段将尝试独立申请租约。从线程的角度来看,这似乎应该没问题,因为融合中断意味着 Stage1 的输出将在被 Stage2 消耗之前被检查点。

标签: google-cloud-dataflow

解决方案


是的,使用键来限制并行性会很好。如果您实际上没有使用状态,则可以使用 GroupByKey 而不是 KeyedState。

使用二级租赁系统也可以,尽管您正确地指出了融合可能存在的问题。这里的主要困难是区分两个融合的 DoFn(永远不会同时执行并且可以共享租约)与并行处理不同工作项的两个 DoFn。如果从外部系统获取/释放租约的成本太高而无法按元素执行,您可以使用某种两级系统,其中工作人员拥有一个每个工作人员(静态)租赁管理器,可以快速服务租赁请求/释放由次级系统的租约在本地支持的参数,这些租约是在更大的时间范围内获取/释放的。这可以很好地用于流式传输和批处理。

另一种选择可能是设置位于第三方系统前面的代理服务并处理全局吞吐量限制。

对于所有这些,如果工人大部分时间都在空闲等待租约,则需要考虑对自动缩放的任何不利影响。


推荐阅读