python - 未从 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。
解决方案
我了解到您想要构建一个自动流程,将聚合数据从 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
推荐阅读
- c# - 授权属性标签不起作用 ASP Web API
- html - 如何使网格的第一个和最后一个元素与其他元素的大小不同?
- c++ - 使用 QT 进程或线程来运行函数?
- python - 错误未在除块中捕获
- javascript - 使用两台设备登录同一帐户时,Firebase 没有给我真实数据
- c - 比较'__libc_multiple_threads'的逻辑在哪里?
- c# - Linq SelectMany 会导致每个内部集的内存分配?
- angular - 如何为 NgRedux 编写测试用例
- javascript - 我想用数组中的下一个值更改状态值
- r - 在 Rstudio 中使用 if 和 else 语句定义分段函数