使用concurrent.futures上传200万个文件(从EC2到S3大约每个30 KB),ThreadPool需要很多时间

时间:2019-06-23 14:16:17

标签: python amazon-s3 python-multithreading concurrent.futures

我们有一个要求,我们需要上传大约200万个文件(从EC2实例到S3大约每个30 KB)。我们正在使用python,boto3和current.futures模块来尝试实现这一目标。以下是伪代码

import concurrent.futures
from concurrent.futures import ThreadPoolExecutor

class UploadToS3:

    def upload(self, file_path):
        try:
            s3 = boto3.resource('s3')
            bucket = s3.Bucket('xxxxxxxxxx')
            destination_file_path =  'yyyyy'
            bucket.upload_file(file_path,destination_file_path)
            del s3
        except (Exception)  as e :
            print(e)

    def upload_files(self, file_paths):
        with concurrent.futures.ThreadPoolExecutor(max_workers=2000) as executor:  
            tracker_futures = []  
            for file_path in file_paths:
                tracker_futures.append(executor.submit(self.upload,file_path)) 
        for future in concurrent.futures.as_completed(tracker_futures):
                tracker_futures.remove(future)
                del future

但是我们发现每小时只能上传约78000个文件,增加线程数并没有多大效果,我们认为这是由于GIL所致,当我们尝试使用ProcessPoolExecutor时,我们遇到了问题,因为boto3对象不可拾取。关于如何克服这种情况的任何建议

1 个答案:

答案 0 :(得分:1)

根据我的一般经验,这听起来确实不错-每秒约21个文件。

可能更好的工作是:

  • 将200万个文件压缩(或以其他方式混淆)成一个巨大的存档文件。
  • 将该存档文件上传到与S3存储桶相同的AWS数据中心中的EC2实例。
  • 将文件解压缩到EC2实例上。
  • 在EC2实例上运行Python脚本。

这将减少每次S3上载的往返网络时间,因为所有内容都将在AWS内。但是,您仍然可能会遇到并发上传数量和/或每秒上传数量的限制。

通常-从DOS到Windows,再到Linux到S3,等等-大量的小文件往往需要较长的很多来处理/上传/等。比相同数量的数据更少,更大的文件。

尽管S3似乎比许多其他系统做得更好,但您可能还想考虑(如果尚未这样做)设置S3文件夹,以使200万个文件不在一个目录中(等效)。但是,根据文件的命名方案和文件的最终用途,这可能很容易实现,也可能不太容易。