首页 > 解决方案 > 未从 Google Cloud Functions 执行的 Python shell 命令

问题描述

我正在尝试构建一个自动流程,将聚合数据从 BigQuery 传输到 redshift。读了很多我发现最好的方法是这样的:

BigQuery -> 导出到 Google 云存储 -> 使用 gsutil 传输到 S3 -> 从 CSV 复制到 Redshift 上的表中。

我把它做成了一个 python 脚本,从我的电脑上运行它似乎一切正常。

但是做了一些测试,我发现直接从 Cloud Shell 使用 gsutil 可以加快文件传输速度。似乎亚马逊和谷歌有一些专用的数据管道或其他东西。

我正在尝试将传输过程移动到我将通过请求触发的谷歌云函数(在 python 中,但只要它有效,语言最终无关紧要)。使用子进程和操作系统。都没有奏效。似乎通常来自 python 函数的 Shell 命令似乎不起作用。

这是 Cloud Function 的代码,当从 Cloud Shell 手动运行时,它可以完美运行:

import subprocess

def hello_world(request):
    data = subprocess.call('gsutil -m cp gs://bucket/file.csv s3://bucket/',shell=True)
    print(data)
    return 'Success!'

传输文件后,我将为插入 Redshift 表的 lambda 函数创建一些 S3 触发器。

我读到这个:如何在没有任何手动活动的情况下将数据从谷歌云存储传输到 S3?

但是调度程序对我没有多大意义?也许我做错了什么。我似乎可以提出要求?但这并不能解决shell命令不被执行的问题。

如果有更好的选择,我愿意接受。是否值得寻找相反的方法?在 AWS 上使用 Lambda 和 gsutil。

标签: pythonamazon-web-servicesamazon-s3google-cloud-platformgoogle-cloud-storage

解决方案


我了解到您想要构建一个自动流程,将聚合数据从 BigQuery 传输到 redshift。

不幸的是,Cloud Function 环境中不存在 gsutil。

Cloud Function 施加超时 [1]。此超时的最大值为 9 分钟。所以即使是gsutil在Cloud Function的环境下可用,复制大文件也可能会超过超时时间。

如果知道发生了哪个文件更改对您的情况至关重要,那么另一种方法是设置 Cloud Pub/Sub [2] 并向其注册对象更改 [3]。

使用订阅此 Cloud Pub/Sub 的 AppEngine 或 Compute Engine 虚拟机,当发生文件更改时,它们将收到指示此更改的事件。他们可以使用 Amazon 的 API [4](在 AppEngine 的情况下)或 gsutil-rsync(在 Compute Engine 的情况下)将文件更改同步到 Amazon S3。

如果知道发生了哪个文件更改对您的用例来说并不重要,那么在 Compute Engine 虚拟机中设置一个 cron 作业来运行 gsutil-rsync 可以实现相同的目标。

请注意,来自云存储的传出网络带宽会产生成本 [5]。您可以设置预算警报 [6] 以避免因同步大文件而被多收费用。

[1] https://cloud.google.com/functions/docs/concepts/exec#timeout

[2] https://cloud.google.com/storage/docs/pubsub-notifications

[3] https://cloud.google.com/storage/docs/reporting-changes

[4] https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html

[5] https://cloud.google.com/storage/pricing#network-egress

[6] https://cloud.google.com/billing/docs/how-to/budgets


推荐阅读