【问题标题】:Python modifies the metadata of GCP storagePython修改GCP存储的元数据
【发布时间】:2021-10-10 07:30:37
【问题描述】:

现在我有一个要求。每当我上传并创建一个新的存储对象时,我都需要修改所有存储对象的元数据。为此,我使用 GCP 的 Function 来实现。

让存储成为函数的触发器。每次上传新的存储对象时,都会使用该函数修改所有对象的元数据。代码如下:

from google.cloud import storage

def hello_gcs(bucket_name, blob_name):
    """Set storage all blob's metadata."""
    bucket_name = 'gcpresource'
    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blobs = storage_client.list_blobs(bucket_name)

    for blob in blobs:
      blob = bucket.get_blob(blob.name)
      CACHE_CONTROL="public, max-age=60480000"
      blob.cache_control = CACHE_CONTROL
      blob.patch()
      print("The metadata for the blob {} is {}".format(blob.name, blob.cache_control))

但是当我将代码放到实际应用程序中时,每次执行它都会显示“函数执行耗时340005毫秒,以状态完成:'超时'”。为此,我设置了最大超时时间为540s,内存为256MB,执行结果还是超时。

作为一个新手,这个问题困扰了我很久,所以想问问是我的代码有问题还是我的存储对象太多导致的?有什么方法可以让函数执行得更快一些?

谢谢!!!!

【问题讨论】:

  • 您的存储桶中有多少 blob?
  • 大约有几万个文件

标签: python-3.x google-cloud-functions google-cloud-storage


【解决方案1】:

当前的问题是您执行 API 调用来更新 blob 的元数据。你有数以万计的文件,你执行数以万计的 API 调用。即使它非常快,每次调用也需要大约 100 毫秒(https 握手、处理/响应),因此您会达到超时。

要解决这个问题,您需要同时执行 API 调用。 2个解决方案

  • 没有那么多可扩展性:在您的代码中,执行异步调用以并行发送多个请求。我不知道如何在 Python 中实现这一点,但在 Go 中,它很有效。您可以同时执行数百个调用,如果您增加内存(以增加 CPU 能力),则可以执行更多。但是,如果文件数量增加,您将达到一次限制。
  • 高度可扩展:编写第一个函数,只读取存储桶中的 blob。每隔一定数量的 blob,比如 500 个,您在 PubSub 中发布一条消息(第 500 个 blob 名称的 base64 编码)。第二个函数监听 PubSub 主题并为每条消息获取 Blob 并更新它们。

在第二个函数中,您需要设置与第一个函数相同数量的 blob 来处理,比如说 500。就像您在不同的云函数上处理 500 个 blob 块一样。

这里的技巧如下:对 blob 名称进行 base64 编码。当您执行list_blob 时,添加参数page_token=<b64_blob_name> 就像这样

...
bucket = storage_client.bucket(bucket_name)
blobs = storage_client.list_blobs(bucket_name, page_token=...)

for blob in blobs:
  ....

确实,页面标记是下一个要处理的文件的 base64 blob 名称。这样,您无需每次都浏览所有存储桶,只需从每个 Cloud Function 中定义的点开始。

【讨论】:

    【解决方案2】:

    如果我理解正确,每次调用该函数时,您都会遍历存储桶中的所有现有 blob 并更改它们的元数据。你真的需要每次都重新处理它们吗?如果您需要更改每个最近上传的 blob 的元数据,您应该考虑使用 GCS 通知:

    在存储桶中上传/创建新文件 -> 触发 GCS 通知 -> PubSub -> 触发 Cloud Function 以更改元数据。

    这样,您一次只需更改一个文件的元数据,Cloud Function 可以自动扩展以同时处理多个文件(或者您可以批量处理)。

    GCS 通知:https://cloud.google.com/storage/docs/pubsub-notifications

    如何启用 GCS 通知的示例:

    gsutil notification create -t TOPIC_NAME -f json -e OBJECT_FINALIZE gs://BUCKET_NAME
    

    参数-e OBJECT_FINALIZE,表示只有在GCS中创建了blob后才会通知。

    【讨论】:

    • 是的,每次上传新的blob,都需要修改存储中所有对象的元数据
    • 我尝试使用pub/sub通知触发函数执行代码,但仍然出现“超时”的问题。请问,如果我的存储中有太多的blob,会导致函数执行太慢吗?我当前的存储中几乎有数万个 Blob
    猜你喜欢
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2018-07-01
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多