繁体   English   中英

Apache Beam 无法正确接收来自 google-cloud-storage 的发布/订阅消息

[英]Apache Beam not properly receiving pub/sub messages from google-cloud-storage

我一直在为这个问题苦苦挣扎,但找不到解决办法。 我正在构建一个管道,该管道从公共谷歌云存储桶中获取数据并对其进行一些转换。 我现在正在努力解决的问题是让 apache 光束在文件上传到云时接收发布/子消息。 有一个名为projects/gcp-public-data---goes-16/topics/gcp-public-data-goes-16 该存储桶是公共的 gos-16 存储桶: https://console.cloud.google.com/storage/browser/gcp-public-data-goes-16/ 特别是我对 ABI-RadC 文件夹感兴趣,所以我用这个初始化了我的订阅者:

gcloud beta pubsub subscriptions create goes16-ABI-data-sub-filtered-test --project my-project --topic projects/gcp-public-data---goes-16/topics/gcp-public-data-goes-16 --message-filter='hasPrefix(attributes.objectId,"ABI-L1b-RadC/")' --enable-message-ordering

因此,这在大多数情况下有效,我大约每 5 分钟按顺序收到 ABI-RadC 消息。 但是,我应该每 5 分钟收到 16 条消息(每个频段一条),因为那是发布到云存储的时间。 但相反,我每 5 分钟收到的消息总是更少(从 2 到 13 条)。 起初,我认为可能是云存储搞砸了,所以我每 5 分钟检查一次谷歌云,谷歌云中有一些文件我没有收到 apache 光束中的消息。 这是我用来调试此问题的代码和 output。

import apache_beam as beam
import os 
import datetime
import json

os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = my_key_path

options = {
    'streaming': True
}

def print_name(message):
    result = json.loads(message)
    file_string = result['name']
    band_id = ((file_string[file_string.find("M6")+1:file_string.find("_G16")]))
    key = ((file_string[file_string.find("s")+1:file_string.find("_e")]))
    print(f"Message recieved at : {datetime.datetime.utcnow()}   key : {key}    band : {band_id}")

runner = 'DirectRunner'
opts = beam.pipeline.PipelineOptions(flags=[], **options)
with beam.Pipeline(runner, options=opts) as p:
    sub_message = (p | 'Sub' >> beam.io.ReadFromPubSub(subscription='my_sub_path'))
    sub_message | 'print name' >> beam.FlatMap(print_name)


    job = p.run()
    if runner == 'DirectRunner':
        job.wait_until_finish()

output:

Message recieved at : 2020-08-16 23:19:05.360728   key : 20202292316171    band : 6C04
Message recieved at : 2020-08-16 23:19:18.464376   key : 20202292316171    band : 6C13
Message recieved at : 2020-08-16 23:19:18.980477   key : 20202292316171    band : 6C14
Message recieved at : 2020-08-16 23:19:19.972165   key : 20202292316171    band : 6C03
Message recieved at : 2020-08-16 23:19:21.116554   key : 20202292316171    band : 6C05
Message recieved at : 2020-08-16 23:24:03.847833   key : 20202292321171    band : 6C04
Message recieved at : 2020-08-16 23:24:16.814699   key : 20202292321171    band : 6C06
Message recieved at : 2020-08-16 23:24:17.393739   key : 20202292321171    band : 6C08
Message recieved at : 2020-08-16 23:29:07.558796   key : 20202292326171    band : 6C04
Message recieved at : 2020-08-16 23:29:21.100278   key : 20202292326171    band : 6C13
Message recieved at : 2020-08-16 23:29:21.771230   key : 20202292326171    band : 6C15
Message recieved at : 2020-08-16 23:34:15.474699   key : 20202292331171    band : 6C15
Message recieved at : 2020-08-16 23:34:16.006153   key : 20202292331171    band : 6C12

密钥只是文件的时间戳。 因此,正如您所见,即使云上存在我丢失的文件,我也不会每 5 分钟收到 16 条消息。 我还尝试在没有--enable-orderinghasPrefix的情况下创建新订阅者,但它不会改变任何东西。 任何帮助表示赞赏。

更新 1所以我决定再做一次测试,看看它是不是 apache 光束,或者我的订阅设置错误。 所以我使用了以下代码:

from concurrent.futures import TimeoutError
from google.cloud import pubsub_v1

# TODO(developer)
project_id = "fire-neural-network"
subscription_id = "custom"
# Number of seconds the subscriber should listen for messages
# timeout = 5.0

subscriber = pubsub_v1.SubscriberClient()
subscription_path = subscriber.subscription_path(project_id, subscription_id)

def callback(message):
    objectId = message.attributes.get('objectId')
    print("Received message: {}".format(objectId))
    message.ack()

streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)
print("Listening for messages on {}..\n".format(subscription_path))

# Wrap subscriber in a 'with' block to automatically call close() when done.
with subscriber:
    try:
        # When `timeout` is not set, result() will block indefinitely,
        # unless an exception is encountered first.
        streaming_pull_future.result()
    except TimeoutError:
        streaming_pull_future.cancel()

检查我是否每 5 分钟收到 16 条消息,并且确实收到了。 所以肯定是我的 apache 光束代码有问题,而不是订阅。 此外,我注意到 apache 光束没有响应我的消息,而上面的代码却可以。 我认为这是错误的原因。 但是我不确定如何让 apache 实际确认消息,尽管我在这里查看过: Dataflow 何时确认来自 PubSubIO 的批处理项目消息? 它说在我尝试过的 pub/sub 之后添加一个 groupbykey,但它仍然不起作用。

import apache_beam as beam
import os 
import datetime
import json

# gcloud beta pubsub subscriptions create custom --project fire-neural-network --topic projects/gcp-public-data---goes-16/topics/gcp-public-data-goes-16 --message-filter='hasPrefix(attributes.objectId,"ABI-L1b-RadC/")' --enable-message-ordering


os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = "/home/n/Keys/fire-neural-network-3b8e8eff4400.json"

options = {
    'streaming': True
}

def print_name(message):
    result = json.loads(message)
    if 'ABI-L1b-RadC' in result['name']:
        file_string = result['name']
        band_id = ((file_string[file_string.find("M6")+1:file_string.find("_G16")]))
        key = ((file_string[file_string.find("s")+1:file_string.find("_e")]))
        print(f"Message recieved at : {datetime.datetime.utcnow()}   key : {key}    band : {band_id}")

output_path = 'gs://fire-neural-network'
runner = 'DirectRunner'
opts = beam.pipeline.PipelineOptions(flags=[], **options)
with beam.Pipeline(runner, options=opts) as p:
        sub_message = (
            pipeline
            | "Read PubSub Messages" >> beam.io.ReadFromPubSub(subscription='mysub')
            | "Window into" >> beam.WindowInto(beam.transforms.window.FixedWindows(5))
            
        )

        grouped_message = (sub_message | "Add Dummy Key" >> beam.Map(lambda elem: (None, elem))
        | "Groupby" >> beam.GroupByKey()
        | "Abandon Dummy Key" >> beam.MapTuple(lambda _, val: val)
        )

        grouped_message | "Write" >> beam.io.WriteToPubSub('mytopic')
        grouped_message | "Print" >> beam.Map(print_name)

    job = p.run()
    if runner == 'DirectRunner':
        job.wait_until_finish()

** 更新 2 ** 我创建了自己的单独测试主题和订阅,以测试是否是与 apache 光束交互的 GCS 订阅导致了问题。 当我创建自己的订阅和主题时,所有消息都已正确确认,只是这个公共存储桶与 apache 光束相结合,具有奇怪的行为。 我可能最终会报废我的光束管道,并使用谷歌的 pub/sub API 编写我自己的未优化管道。

暂无
暂无

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

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