从外部 FTP 服务器下载 5M 的 1MB 大小的存档文件到 AWS S3
Download 5M of 1MB-sized archive files from an external FTP server to AWS S3
问题
我必须将大量 .tar.gz
文件(500 万)下载到 AWS S3,每个文件的大小约为 1 Mb,存储在外部 FTP 服务器上(我没有控制它)。
我的尝试
我已经实现了基于 python 的 concurrent.futures.ThreadPoolExecutor
和 s3fs
模块的解决方案。我针对 10K 文件的子集对其进行了测试,整个过程花费了大约 20 分钟(使用 this approach 下载然后使用 s3fs
存储在 AWS S3 上)。这意味着每分钟处理 10,000 / 20 = 500 个档案。对于 500 万,需要 5M / 500 = 10,000 分钟的处理时间 = 7 天。这次我等不起(时间和成本,我担心 FTP 服务器断开与我的 IP 的连接)。
对于该任务,我使用了一个 r5.metal
实例,这是我在 EC2 目录中找到的 vCPU (96) 和网络性能最强大的实例之一。
我的问题
所以我问:
- 这个问题的最佳解决方案是什么?
- 有没有不到一周的解决方案?
- 对于这项工作,是否有比
r5.metal
更好的实例?
- AWS 上是否有经济高效且可扩展的专用服务?
- 在这种特殊情况下,
threading
、multiprocessing
和 asyncio
(以及其他解决方案)之间最适合的是什么?下载 1000 个文件的相同问题,每个文件的大小约为 50 Mb。
非常感谢任何帮助。
您可以采用两种方法...
使用亚马逊 EC2
将文件子列表(100 个?)传递给您的 Python 脚本。让它循环遍历文件,依次将每个文件下载到本地磁盘。然后,使用 boto3 将其复制到 Amazon S3。
不要 担心如何将其编写为线程或执行花哨的异步操作。相反,只有 运行 很多 Python 脚本并行,每个脚本都有自己的要复制的文件列表。一旦你得到足够多的运行并行(只是运行后台使用&
的脚本,监控实例以确定瓶颈所在——你可能会发现CPU 而 RAM 不是问题 - 它更可能是远程 FTP 服务器只能处理一定数量的查询 and/or 数据带宽。
然后您应该能够确定 'sweet spot' 以最小的成本获得最快的吞吐量(如果这甚至是一个考虑因素)。您甚至可以 运行 多个并行的 EC2 实例,每个 运行 并行执行脚本。
使用 AWS Lambda
将一小部分文件名推送到 Amazon SQS 队列。
然后,创建一个从 SQS 队列触发的 AWS Lambda 函数。该函数应该从 FTP 服务器检索文件,保存到本地磁盘,然后使用 boto3 将它们复制到 S3。 (请务必在上传到 S3 后删除文件,因为 Lambda 函数容器中只有有限的 space。)
这将使用 AWS Lambda 的并行功能来并行执行操作。默认情况下,您可以并行 运行 1000 个 Lambda 函数,但您可以请求增加此限制。
首先使用推入 SQS 队列的几个文件对其进行测试。如果可行,请发送几千条消息并查看它处理负载的情况。您也可以在 Lambda 中使用内存分配,但最低级别可能就足够了。
和解
假设文件将无法下载。与其重试,不如让它们失败。
然后,在所有脚本 运行(在 EC2 或 Lambda 中)之后,将上传到 S3 的文件与您的文件主列表进行核对。请注意,在 S3 中列出文件可能有点慢(每次 API 调用检索 1000 个文件)因此您可能想要使用 Amazon S3 Inventory,它可以提供列出所有对象的每日 CSV 文件。
一般
无论您采用哪种方法,事情都会出错。例如,远程 FTP 服务器可能只允许有限数量的连接。它可能有带宽限制。下载将随机失败。由于这是一次性的 activity,因此仅下载文件比制作世界上最好的流程更重要。如果您不想等待 34 天才能下载,那么您必须一些东西 快速进行,因此至少在您调整和改进过程的同时进行下载。
祝你好运!让我们知道您的进展!
问题
我必须将大量 .tar.gz
文件(500 万)下载到 AWS S3,每个文件的大小约为 1 Mb,存储在外部 FTP 服务器上(我没有控制它)。
我的尝试
我已经实现了基于 python 的 concurrent.futures.ThreadPoolExecutor
和 s3fs
模块的解决方案。我针对 10K 文件的子集对其进行了测试,整个过程花费了大约 20 分钟(使用 this approach 下载然后使用 s3fs
存储在 AWS S3 上)。这意味着每分钟处理 10,000 / 20 = 500 个档案。对于 500 万,需要 5M / 500 = 10,000 分钟的处理时间 = 7 天。这次我等不起(时间和成本,我担心 FTP 服务器断开与我的 IP 的连接)。
对于该任务,我使用了一个 r5.metal
实例,这是我在 EC2 目录中找到的 vCPU (96) 和网络性能最强大的实例之一。
我的问题
所以我问:
- 这个问题的最佳解决方案是什么?
- 有没有不到一周的解决方案?
- 对于这项工作,是否有比
r5.metal
更好的实例? - AWS 上是否有经济高效且可扩展的专用服务?
- 在这种特殊情况下,
threading
、multiprocessing
和asyncio
(以及其他解决方案)之间最适合的是什么?下载 1000 个文件的相同问题,每个文件的大小约为 50 Mb。
非常感谢任何帮助。
您可以采用两种方法...
使用亚马逊 EC2
将文件子列表(100 个?)传递给您的 Python 脚本。让它循环遍历文件,依次将每个文件下载到本地磁盘。然后,使用 boto3 将其复制到 Amazon S3。
不要 担心如何将其编写为线程或执行花哨的异步操作。相反,只有 运行 很多 Python 脚本并行,每个脚本都有自己的要复制的文件列表。一旦你得到足够多的运行并行(只是运行后台使用&
的脚本,监控实例以确定瓶颈所在——你可能会发现CPU 而 RAM 不是问题 - 它更可能是远程 FTP 服务器只能处理一定数量的查询 and/or 数据带宽。
然后您应该能够确定 'sweet spot' 以最小的成本获得最快的吞吐量(如果这甚至是一个考虑因素)。您甚至可以 运行 多个并行的 EC2 实例,每个 运行 并行执行脚本。
使用 AWS Lambda
将一小部分文件名推送到 Amazon SQS 队列。
然后,创建一个从 SQS 队列触发的 AWS Lambda 函数。该函数应该从 FTP 服务器检索文件,保存到本地磁盘,然后使用 boto3 将它们复制到 S3。 (请务必在上传到 S3 后删除文件,因为 Lambda 函数容器中只有有限的 space。)
这将使用 AWS Lambda 的并行功能来并行执行操作。默认情况下,您可以并行 运行 1000 个 Lambda 函数,但您可以请求增加此限制。
首先使用推入 SQS 队列的几个文件对其进行测试。如果可行,请发送几千条消息并查看它处理负载的情况。您也可以在 Lambda 中使用内存分配,但最低级别可能就足够了。
和解
假设文件将无法下载。与其重试,不如让它们失败。
然后,在所有脚本 运行(在 EC2 或 Lambda 中)之后,将上传到 S3 的文件与您的文件主列表进行核对。请注意,在 S3 中列出文件可能有点慢(每次 API 调用检索 1000 个文件)因此您可能想要使用 Amazon S3 Inventory,它可以提供列出所有对象的每日 CSV 文件。
一般
无论您采用哪种方法,事情都会出错。例如,远程 FTP 服务器可能只允许有限数量的连接。它可能有带宽限制。下载将随机失败。由于这是一次性的 activity,因此仅下载文件比制作世界上最好的流程更重要。如果您不想等待 34 天才能下载,那么您必须一些东西 快速进行,因此至少在您调整和改进过程的同时进行下载。
祝你好运!让我们知道您的进展!