繁体   English   中英

限制 Beam/Dataflow stream 作业中已处理元素的数量

[英]Limit number of processed elements in Beam/Dataflow stream job

我有一个在 Dataflow 运行器上运行的 Beam 流式传输作业。 它从 PubSub 加载请求(使用 Python 的apache_beam.io.ReadFromPubSub ),然后从 BigTable 获取数据,对数据进行大量计算并再次写入 PubSub。

with beam.Pipeline(options=pipeline_options) as pipeline:
        (
            pipeline
            | "Receive" >> beam.io.ReadFromPubSub(topic=TOPIC_READ)
            | "Parse" >> beam.ParDo(Parse())
            | "Fetch" >> beam.ParDo(FetchFromBigtable(project, args.bt_instance, args.bt_par, args.bt_batch))
            | "Process" >> beam.ParDo(Process())
            | "Publish" >> beam.io.WriteToPubSub(topic=TOPIC_WRITE)
        )

基本上我不需要任何窗口,我只想限制在一台机器上并行处理的元素数量(即通过工人数量控制并行度)。 否则在繁重的计算过程中会导致 memory 溢出,我还需要限制 BigTable 请求的速率。

我使用的是标准的 2 CPU 机器,所以我希望它可以并行处理 2 个元素 - 我还设置了 --number_of_worker_harness_threads --number_of_worker_harness_threads=2--sdk_worker_parallelism=1 出于某种原因,尽管我看到许多元素由多个线程并行处理,这会导致 memory 和速率限制问题。 我猜这些是基于日志并行处理的包(例如work: "process_bundle-105" )。

在此处输入图像描述

我试图通过在processElement中使用信号量来破解它(每个 DoFN 实例只处理一个元素)并且它可以工作,但是自动缩放并没有启动,它看起来像一个纯粹的破解,可能会产生其他后果。

你会推荐什么? 如何限制要处理的并行包的数量? 理想情况下,每个工人线束线只有一束? 光束/数据流是否适合这种用例,还是使用带有自动缩放功能的普通 kubernetes 来实现它更好?

编辑:

在梁 SDK 2.28.0 上运行

我想限制并行性,但我没有很好地描述导致我得出这个结论的症状。

  1. 有时我在Fetch阶段超时
Deadline of 60.0s exceeded while calling functools.partial(<bound method PartialRowsData._read_next of <google.cloud.bigtable.row_data.PartialRowsData object at 0x7f16b405ba50>>)
  1. Process阶段处理一个元素会显着减慢(到几分钟而不是几秒钟),有时甚至会卡住(可能是因为 memory 问题)。

以下是在Process阶段(单线程)中由jsonPayload.workerjsonPayload.portability_worker_id过滤的 1 个元素处理之前和之后记录的一名工作人员的日志(即,我希望这些应该是来自一个容器的日志)。 我可以看到一瞬间处理了超过 12 个元素。

流程阶段的日志

我通过使用Stateful Processing成功解决了 Dataflow 和 Elasticsearch 的此类问题。 如果您的接收器无法跟上管道的 rest 的速度,您可以使用GroupIntoBatches来降低并行度。

据我了解,状态由运行程序在每个键每个窗口的基础上维护。 要使用有状态处理,您的数据需要有键。 这些键可以是任意的,并且被用于使用元素的 DoFn 忽略。

您提到您不需要开窗,如果您当前没有使用任何开窗,这意味着您正在使用默认的单数 Global Window。 在这种情况下,您任意分配给数据的不同键的数量将是维护的最大并行状态数。 请注意,此解决方案不适用于所有跑步者,因为并非所有跑步者都全局支持有状态处理。

Dataflow 每个核心启动一个 SDK 工作容器,因此在您的情况下,每台机器将有 2 个工作容器(进程)。 每个工作进程都有一个无界线程池来处理包,但我认为由于 python GIL,一次只能用一个线程处理一个包。

您可以--experiments no_use_multiple_sdk_containers将 sdk 容器编号限制为 1(因为您的用例似乎不太关心吞吐量)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM