数据流自动缩放不会提高性能

时间:2018-07-24 21:21:42

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

我正在构建一个数据流管道,该管道将从pubsub中读取数据并将请求发送到第三方API。管道使用THROUGHPUT_BASED自动缩放。

但是,当我对其进行负载测试时,它自动缩放到4个工作量以赶上pubsub中的积压工作后,但是似乎在工作之间分散了相同的工作负载事件,但是总体吞吐量并未显着增加。

Number of unacknowledged messages in pubsub. The peak is when traffic stopped going in ^ pubsub中未确认​​的消息数。高峰是流量停止进入的时间

Bytes sent from each worker. ^每个工作者发送的字节。高峰是最初的工人。随着将更多的工作人员添加到池中,工作量被卸载,而不是每个人都承担更多的工作量。 CPU利用率看起来相同,初始工作人员的峰值利用率低于30%。

The history of worker spawned ^工人的历史产生了。

感觉好像某处受到限制,但是我很难知道该限制是什么。我每秒提取不到300条消息,每条消息大约1kb。

更新: 我在使用TextIO的批处理作业和使用PubSubIO的流处理作业之间进行了另一轮比较,两者均使用“ n1-standard-8”计算机,固定的工作人员数量为15。批处理的作业速度提高到450个元素/秒,但流式处理作业仍达到230个元素/秒的峰值。限制似乎来自源头。尽管我不确定有什么限制。

更新2 这是重现此问题的简单代码段。您将需要手动将工程数量设置为1和5,并比较管道处理的元素数量。您将需要一个负载测试器来有效地将消息发布到该主题。

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 个答案:

答案 0 :(得分:0)

考虑到以下因素:

  1. 从PubSubIO切换到TextIO并没有改善。
  2. 从3名工人改为15名工人并没有改善。
  3. 该批作业的速度高达450个元素/秒,但流达到230个元素/秒的峰值
  4. 有一个转换将REST请求发送到第三方API,这需要花费数小时的时间。
  5. 在测试中,取消转换将吞吐量从120个元素/秒增加到400个元素/秒。

问题似乎不在于PubSub方面。根据{{​​3}},您可能正在重载第三方API。客户端文档中解释了相同的效果,而不是第三方API:

  

一个客户端可能积压了消息,因为   它没有能力处理传入的数量   消息,但网络上的另一个客户端确实具有该能力。   第二个客户端可以减少总体积压,但没有得到   因为第一个客户端无法将其消息发送到   第二个客户很快。这降低了   正在处理,因为邮件卡在第一个客户端上。

     

创建积压的消息消耗内存,CPU和带宽   资源,因为客户端库继续扩展消息的   确认截止日期。

[...]

  

更一般而言,对流控制的需求表明消息是   被出版的速度高于被消费的速度。如果这   是持久状态,而不是消息量激增,请考虑   增加订户客户端实例和计算机的数量。

如果您只能在PubSub上工作以改善结果,并且您认为实现此目标的方法是扩展元素的acknowledgement deadline time,则可以通过访问this documentation并手动编辑订阅来对其进行测试。要使用Java以编程方式进行操作,请查看herethis文档,分别介绍如何管理订阅和更改ackDeadlineSeconds