Google cloud platform 数据流自动缩放不会提高性能
我正在构建一个数据流管道,它从pubsub读取数据并向第三方API发送请求。管道使用基于吞吐量的自动缩放 然而,当我对它进行负载测试时,在它自动调整为4个工作以赶上pubsub中的积压工作之后,似乎相同的工作负载在工作之间分布,但总体吞吐量没有显著增加 ^pubsub中未确认的邮件数。高峰是车辆停止进入的时候 ^从每个工作进程发送的字节数。峰值是第一个工人。随着更多的工作人员添加到池中,工作负载将被卸载,而不是每个人都承担更多的工作负载。CPU利用率看起来是一样的,初始工作线程的峰值利用率低于30% ^工人的历史产生了 这感觉要么是某个地方受到了限制,但我很难看到限制是什么。我每秒只收到不到300条消息,每条消息大约1kb 更新: 我对使用TextIO的批处理作业和使用PubSubIO的流式作业进行了另一轮比较,这两种作业都使用“n1-standard-8”机器,工人数量固定为15人。批处理作业上升到450个元素/秒,但流式作业仍以230个元素/秒达到峰值。看来限制来自源头。虽然我不确定限制是什么 更新2 下面是一个简单的代码片段来重现这个问题。您需要手动将工作数设置为1和5,并比较管道处理的元素数。您需要一个负载测试仪来高效地将消息发布到主题。Google cloud platform 数据流自动缩放不会提高性能,google-cloud-platform,google-cloud-dataflow,apache-beam,google-cloud-pubsub,Google Cloud Platform,Google Cloud Dataflow,Apache Beam,Google Cloud Pubsub,我正在构建一个数据流管道,它从pubsub读取数据并向第三方API发送请求。管道使用基于吞吐量的自动缩放 然而,当我对它进行负载测试时,在它自动调整为4个工作以赶上pubsub中的积压工作之后,似乎相同的工作负载在工作之间分布,但总体吞吐量没有显著增加 ^pubsub中未确认的邮件数。高峰是车辆停止进入的时候 ^从每个工作进程发送的字节数。峰值是第一个工人。随着更多的工作人员添加到池中,工作负载将被卸载,而不是每个人都承担更多的工作负载。CPU利用率看起来是一样的,初始工作线程的峰值利用率低
包调试;
导入java.io.IOException;
导入org.apache.beam.runners.dataflow.DataflowRunner;
导入org.apache.beam.runners.dataflow.options.DataflowPipelineOptions;
导入org.apache.beam.runners.dataflow.options.DataflowPipelineWorkerPoolOptions;
导入org.apache.beam.sdk.Pipeline;
导入org.apache.beam.sdk.PipelineResult;
导入org.apache.beam.sdk.io.gcp.pubsub.PubsubIO;
导入org.apache.beam.sdk.options.pipelineoptions工厂;
导入org.apache.beam.sdk.transforms.DoFn;
导入org.apache.beam.sdk.transforms.ParDo;
公共类调试管道{
@抑制警告(“串行”)
公共静态PipelineResult main(字符串[]args)引发IOException{
/*******************************************
*设置-生成选项。
********************************************/
DataflowPipelineOptions=PipelineOptionFactory.fromArgs(args).withValidation()
.as(DataflowPipelineOptions.class);
options.setRunner(DataflowRunner.class);
options.setAutoscalingAlgorithm(
DataflowPipelineWorkerPoolOptions.AutoscalingAlgorithmType.Throughts(基于U);
//自动缩放将在n/15和n个工作人员之间进行缩放,因此这里从1到15
选项。setMaxNumWorkers(15);
//250GB的默认值高得离谱,我们不需要对每个工人都这么多
选项。setDiskSizeGb(32);
//手动配置缩放(即1对5进行比较)
选项。setNumWorkers(5);
//调试管道
Pipeline=Pipeline.create(选项);
管道
.apply(publisubio.readStrings()
.fromSubscription(“您的订阅”))
//这是我真正关心的转换
//向某个第三方端点发送REST请求。
.apply(“sleep”,ParDo.of(new DoFn)(){
@过程元素
public void processElement(ProcessContext c)引发InterruptedException{
睡眠(500);
c、 输出(c.element());
}
}));
返回管道。run();
}
}
考虑到:
确认截止时间
,那么您可以通过访问和手动编辑订阅来测试它。要使用Java以编程方式完成此操作,请查看和文档,分别介绍如何管理订阅和更改ackDeadlineSeconds
古董
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();
}
}