我正在构建一个数据流管道,该管道将从pubsub中读取数据并将请求发送到第三方API。管道使用THROUGHPUT_BASED
自动缩放。
但是,当我对其进行负载测试时,它自动缩放到4个工作量以赶上pubsub中的积压工作后,但是似乎在工作之间分散了相同的工作负载事件,但是总体吞吐量并未显着增加。
^ pubsub中未确认的消息数。高峰是流量停止进入的时间
^每个工作者发送的字节。高峰是最初的工人。随着将更多的工作人员添加到池中,工作量被卸载,而不是每个人都承担更多的工作量。 CPU利用率看起来相同,初始工作人员的峰值利用率低于30%。
感觉好像某处受到限制,但是我很难知道该限制是什么。我每秒提取不到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();
}
}
答案 0 :(得分:0)
考虑到以下因素:
问题似乎不在于PubSub方面。根据{{3}},您可能正在重载第三方API。客户端文档中解释了相同的效果,而不是第三方API:
一个客户端可能积压了消息,因为 它没有能力处理传入的数量 消息,但网络上的另一个客户端确实具有该能力。 第二个客户端可以减少总体积压,但没有得到 因为第一个客户端无法将其消息发送到 第二个客户很快。这降低了 正在处理,因为邮件卡在第一个客户端上。
创建积压的消息消耗内存,CPU和带宽 资源,因为客户端库继续扩展消息的 确认截止日期。
[...]
更一般而言,对流控制的需求表明消息是 被出版的速度高于被消费的速度。如果这 是持久状态,而不是消息量激增,请考虑 增加订户客户端实例和计算机的数量。
如果您只能在PubSub上工作以改善结果,并且您认为实现此目标的方法是扩展元素的acknowledgement deadline time
,则可以通过访问this documentation并手动编辑订阅来对其进行测试。要使用Java以编程方式进行操作,请查看here和this文档,分别介绍如何管理订阅和更改ackDeadlineSeconds
。