【问题标题】:Apache Beam Cloud Dataflow Streaming Stuck Side InputApache Beam Cloud Dataflow Streaming Stuck Side Input
【发布时间】:2022-01-03 04:48:06
【问题描述】:

我目前正在 GCP Dataflow 中构建 PoC Apache Beam 管道。在这种情况下,我想使用来自 PubSub 的主要输入和来自 BigQuery 的侧输入来创建流式管道,并将处理后的数据存储回 BigQuery。

侧流水线代码

side_pipeline = (
    p
    | "periodic" >> PeriodicImpulse(fire_interval=3600, apply_windowing=True)
    | "map to read request" >>
        beam.Map(lambda x:beam.io.gcp.bigquery.ReadFromBigQueryRequest(table=side_table))
    | beam.io.ReadAllFromBigQuery()
)

带有侧输入代码的功能

def enrich_payload(payload, equipments):
    id = payload["id"]
    for equipment in equipments:
        if id == equipment["id"]:
            payload["type"] = equipment["type"]
            payload["brand"] = equipment["brand"]
            payload["year"] = equipment["year"]

            break

    return payload

主管道代码

main_pipeline = (
    p
    | "read" >> beam.io.ReadFromPubSub(topic="projects/my-project/topics/topiq")
    | "bytes to dict" >> beam.Map(lambda x: json.loads(x.decode("utf-8")))
    | "transform" >> beam.Map(transform_function)
    | "timestamping" >> beam.Map(lambda src: window.TimestampedValue(
        src,
        dt.datetime.fromisoformat(src["timestamp"]).timestamp()
    ))
    | "windowing" >> beam.WindowInto(window.FixedWindows(30))
)

final_pipeline = (
    main_pipeline
    | "enrich data" >> beam.Map(enrich_payload, equipments=beam.pvalue.AsIter(side_pipeline))
    | "store" >> beam.io.WriteToBigQuery(bq_table)
)

result = p.run()
result.wait_until_finish()

将其部署到 Dataflow 后,一切看起来都很好,没有错误。但后来我注意到enrich data 步骤有两个节点而不是一个。

此外,如您所见,侧面输入卡在输入集合中具有 21 个计数的 Elements Added 和输出集合中的 Elements Added 中的 - 值。

您可以找到完整的管道代码 here 和模拟 pubsub 发布者 here

我已经按照这些文档中的所有说明进行操作:

但仍然发现此错误。请帮我。谢谢!

【问题讨论】:

  • 能否提供完整的python管道代码?所以我可以很容易地复制它。
  • @ewertonvsilva 嗨,我已经添加了完整代码的链接,谢谢你的帮助!
  • 我花了一些时间在它上面,但它仍然没有在最后一个阶段写,接缝一些与窗口有关的东西。但是,我可能会在其他部分遇到一些错误。 1.将此步骤修复为:"timestamp" >> beam.Map(lambda src: window.TimestampedValue( # src,src["timestamp"])),2.在阅读主题时使用订阅:"read" >> beam.io.ReadFromPubSub(subscription=INPUT_SUBSCRIPTION)。修复这些并检查它是否可以帮助您前进。
  • @ewertonvsilva 非常感谢兄弟!我会检查的。

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


【解决方案1】:

这里有一个工作示例:

mytopic = ""
sql = "SELECT station_id, CURRENT_TIMESTAMP() timestamp FROM `bigquery-public-data.austin_bikeshare.bikeshare_stations` LIMIT 10"

def to_bqrequest(e, sql):
    from apache_beam.io import ReadFromBigQueryRequest
    yield ReadFromBigQueryRequest(query=sql)
     

def merge(e, side):
    for i in side:
        yield f"Main {e.decode('utf-8')} Side {i}"

pubsub = p | "Read PubSub topic" >> ReadFromPubSub(topic=mytopic)

side_pcol = (p | PeriodicImpulse(fire_interval=300, apply_windowing=False)
               | "ApplyGlobalWindow" >> WindowInto(window.GlobalWindows(),
                                           trigger=trigger.Repeatedly(trigger.AfterProcessingTime(5)),
                                           accumulation_mode=trigger.AccumulationMode.DISCARDING)
               | "To BQ Request" >> ParDo(to_bqrequest, sql=sql)
               | ReadAllFromBigQuery()
            )

final = (pubsub | "Merge" >> ParDo(merge, side=beam.pvalue.AsList(side_pcol))
                | Map(logging.info)
        )                    
    
p.run()

请注意,这使用GlobalWindow(这样两个输入具有相同的窗口)。我使用了处理时间触发器,以便窗格包含多行。 5 是任意选择的,使用1 也可以。

请注意,侧输入和主输入之间的数据匹配是非确定性的,您可能会看到较旧的触发窗格中的波动值。

理论上,使用FixedWindows 应该可以解决这个问题,但我无法让FixedWindows 工作。

【讨论】:

  • 非常感谢兄弟!我先试试
  • 孔床单老兄,它的工作!太感谢了!但不幸的是,在我尝试了您的解决方案后仅一个小时,赏金就结束了。你还真的想要赏金吗?要的话我给你
  • 很高兴看到它成功了!哦,我很遗憾,我在度假时看到了这个问题,我正等着回来开始编码:D 不需要创建新的赏金,我很高兴这对你有用
  • 我认为FixedWindows 不起作用的原因是它通过PCollection 水印触发聚合。当管道启动时,它只接收一个元素,直到下一个 PeriodicImpulse 发送另一个 PColletion(在我的代码中一个小时后),因此它不会触发默认触发器 trigger.AfterWatermark,因为没有元素水印通过该窗口.这就是trigger.AfterProcessingTime 起作用的原因,因为它不依赖于元素水印。
猜你喜欢
  • 1970-01-01
  • 2018-01-25
  • 1970-01-01
  • 2020-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-15
  • 1970-01-01
相关资源
最近更新 更多