繁体   English   中英

如何在 Python 中高效地将小文件上传到 Amazon S3

[英]How to upload small files to Amazon S3 efficiently in Python

最近,我需要实现一个程序,以尽快将驻留在 Amazon EC2 中的文件上传到 Python 中的 S3。 文件大小为30KB。

我尝试了一些解决方案,使用多线程、多处理、协程。 以下是我在 Amazon EC2 上的性能测试结果。

3600(文件数量)*30K(文件大小)~~105M(总计)--->

       **5.5s [ 4 process + 100 coroutine ]**
       10s  [ 200 coroutine ]
       14s  [ 10 threads ]

代码如下所示

用于多线程

def mput(i, client, files):
    for f in files:
        if hash(f) % NTHREAD == i:
            put(client, os.path.join(DATA_DIR, f))


def test_multithreading():
    client = connect_to_s3_sevice()
    files = os.listdir(DATA_DIR)
    ths = [threading.Thread(target=mput, args=(i, client, files)) for i in range(NTHREAD)]
    for th in ths:
        th.daemon = True
        th.start()
    for th in ths:
        th.join()

对于协程

client = connect_to_s3_sevice()
pool = eventlet.GreenPool(int(sys.argv[2]))

xput = functools.partial(put, client)
files = os.listdir(DATA_DIR)
for f in files:
    pool.spawn_n(xput, os.path.join(DATA_DIR, f))
pool.waitall()

对于多处理 + 协程

def pproc(i):
    client = connect_to_s3_sevice()
    files = os.listdir(DATA_DIR)
    pool = eventlet.GreenPool(100)

    xput = functools.partial(put, client)
    for f in files:
        if hash(f) % NPROCESS == i:
            pool.spawn_n(xput, os.path.join(DATA_DIR, f))
    pool.waitall()


def test_multiproc():
    procs = [multiprocessing.Process(target=pproc, args=(i, )) for i in range(NPROCESS)]
    for p in procs:
        p.daemon = True
        p.start()
    for p in procs:
        p.join()

机器配置为Ubuntu 14.04,2个CPU(2.50GHz),4G内存

达到的最高速度约为19Mb/s (105 / 5.5) 总的来说,速度太慢了。 有什么办法可以加快速度? stackless python 可以做得更快吗?

此处提供了使用 Python boto SDK 并行上传到 Amazon S3 的示例:

除了自己编写代码,您还可以考虑调用AWS 命令​​行界面 (CLI) ,它可以并行上传。 它也是用 Python 编写的并使用 boto。

我最近需要将大约 5 TB 的小文件上传到 AWS,并通过在 ~/.aws/config 文件中设置更高的“max_concurrent_request”值来达到 ~750Mbits(每台服务器 1 Gb 连接)的完整网络带宽。

我通过 bash for 循环启动多个上传作业并将这些作业发送到不同的服务器,从而进一步加快了进程。

我也试过 python 例如。 s3-parallel-put,但我认为这种方法更快。 当然,如果文件太小,应该考虑:压缩 --> 上传到 EBS /S3 并在那里解压

这是一些可能有帮助的代码。

$cat .aws/config 
[default]
region = eu-west-1
output = text
s3 =
    max_concurrent_requests = 100

比启动多个 aws 复制作业,例如:

for folder in `ls`; do aws s3 cp $folder s3://<bucket>/$folder/whatever/; done

我和你有同样的问题。 我的解决方案是将数据发送到 AWS SQS,然后使用 AWS Lambda 将它们保存到 S3。

所以数据流看起来:app -> SQS -> Lambda -> S3

整个过程是异步的,但接近实时:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM