Dataflow如何自动扩展和分配工作量?

时间:2018-08-02 15:27:27

标签: google-cloud-platform google-cloud-dataflow apache-beam

在阅读this question之后,我仍然对Dataflow / Apache Beam如何分配工作负载有一些疑问。我遇到的问题可以通过以下代码进行演示:

package debug;

import java.io.IOException;

import org.apache.beam.runners.dataflow.DataflowRunner;
import org.apache.beam.runners.dataflow.options.DataflowPipelineOptions;
import org.apache.beam.runners.dataflow.options.DataflowPipelineWorkerPoolOptions;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.io.gcp.pubsub.PubsubIO;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.ParDo;

public class DebugPipeline {
    @SuppressWarnings("serial")
    public static PipelineResult main(String[] args) throws IOException {

        /*******************************************
         * SETUP - Build options.
         ********************************************/

        DataflowPipelineOptions options = PipelineOptionsFactory.fromArgs(args).withValidation()
                .as(DataflowPipelineOptions.class);
        options.setRunner(DataflowRunner.class);
        options.setAutoscalingAlgorithm(
                DataflowPipelineWorkerPoolOptions.AutoscalingAlgorithmType.THROUGHPUT_BASED);
        // Autoscaling will scale between n/15 and n workers, so from 1-15 here
        options.setMaxNumWorkers(15);
        // Default of 250GB is absurdly high and we don't need that much on every worker
        options.setDiskSizeGb(32);
        // Manually configure scaling (i.e. 1 vs 5 for comparison)
        options.setNumWorkers(5);

        // Debug Pipeline
        Pipeline pipeline = Pipeline.create(options);
        pipeline
            .apply(PubsubIO.readStrings()
                    .fromSubscription("your subscription"))
            // this is the transform that I actually care about. In production code, this will
            // send a REST request to some 3rd party endpoint.
            .apply("sleep", ParDo.of(new DoFn<String, String>() {
                @ProcessElement
                public void processElement(ProcessContext c) throws InterruptedException {
                    Thread.sleep(500);
                    c.output(c.element());
                }
            }));

        return pipeline.run();
    }
}

比较使用1个工人和5个工人时的最大吞吐量,而不是后者执行5倍的效率,它仅稍微提高了效率。这让我想知道以下问题:

  1. 假设每个工作人员正在使用4个vCPU,是否每个线程都绑定到特定的DoFn,或者如果需要提高性能,可以在给定的时刻在所有线程上调用相同的DoFn?
  2. 假设工作人员不止一个,每个工作人员都会获得完整的管道,即每个Transform的至少一个实例(包括源)吗?
  3. Dataflow / Apache Beam如何确定要更频繁地调用哪个Transform?是否将创建更多占用更多CPU资源的DoFn实例?更长的挂墙时间?还是每个Transform被复制相同的时间?
  4. 根据Apache programming guide,后端等于asynchronous “job”。这是否意味着每个DoFn实例都是异步处理的?
  5. 同样,在提供的示例代码中,将如何异步处理“ sleep”转换?
  6. 在生产代码中,Thread.sleep替换为对第三方API的同步http请求。异步过程是否意味着它将同步客户端转换为异步客户端?

更新

还有一个额外的问题: Dataflow documentation对PubSubIO的评论是:

  

在极端情况下(例如,具有大发布批次的Cloud Pub / Sub订阅或具有很高延迟的接收器),已知自动缩放会变得粗粒度。

您能否扩展以下内容:

  1. 大型出版批次是什么意思?即大批量还是大批量?

  2. 高延迟接收器是否在接收器之前的转换中包括高延迟?

  3. 粗粒度行为是什么?

1 个答案:

答案 0 :(得分:1)

  1. 可以在给定时刻(look in the blue star)
  2. 在所有线程上调用DoFns
  3. 是的,每个工人都会处理一条完整的管道
  4. Cloud Dataflow服务执行各种optimizations:融合和合并
  5. 可以执行的步骤,不依赖数据
  6. 可以同时在不同的工作进程上处理“睡眠”,并按顺序发送到队列。
  7. 取决于数据依赖项