高效地将大量数据传输到S3
项目描述
S3AM(发音为ˈskrēm),是一个快速、并行、流式传输S3的工具。S3中的对象可以从任何支持本地安装的libcurl和远程服务器支持字节范围请求的URL进行流式传输,例如file://、ftp://(许多服务器)和http://(一些服务器)。此外,S3中的对象还可以下载到本地文件系统。上传和下载在中断后都可以恢复。
S3AM旨在用于大文件,已经测试了300GB的文件,但没有对最大文件大小施加固有的限制。虽然它可以用于传输小文件,但您可能会发现,如果文件大小低于,例如,5MB,那么它的性能可能不如其他工具。
S3AM支持使用SSE-C加密上传的文件。
S3AM还可以在存储桶之间以及存储桶内复制对象,而无需在客户端和服务器之间实际传输任何数据。它支持为复制操作的原点和目的地使用单独的SSE-C加密密钥,因此可以用于有效地重新加密对象。
S3AM使用libcurl的PyCurl绑定和Python的multiprocessing模块来绕过Python解释器的锁定争用,以避免与libcurl潜在的线程安全问题。
先决条件
Python 2.7.x、libcurl和pip。
在Ubuntu上,可以使用以下命令安装依赖项:
sudo apt-get install python-dev gcc make libcurl4-openssl-dev libssl-dev
安装
建议您在虚拟环境中安装S3AM。
virtualenv ~/s3am && source ~/s3am/bin/activate pip install s3am
如果您想安装最新不稳定版本,可以运行 pip install --pre s3am。
如果您遇到 libcurl 链接时间 ssl后端(nss)与编译时间 ssl后端不同的错误,则需要将pip安装命令的前缀设置为 PYCURL_SSL_LIBRARY=nss,例如 PYCURL_SSL_LIBRARY=nss pip install --pre s3am。
可选地,添加到 s3am 命令的符号链接,这样在之前使用它之前不需要激活虚拟环境。
mkdir -p ~/bin ln -s ~/s3am/bin/s3am ~/bin
然后,将 ~/bin 添加到您的 PATH 环境变量中。我本想明确告诉您如何修改 PATH,但不幸的是,这取决于各种因素,例如您使用的shell和操作系统。例如,在OS X上,您需要编辑 ~/.profile 并添加以下内容:
export PATH="$HOME/bin:$PATH"
配置
获取AWS的访问密钥和秘密密钥。创建 ~/.aws/credentials 并包含以下内容:
[default] aws_access_key_id=PASTE_YOUR_FOO_ACCESS_KEY_ID_HERE aws_secret_access_key=PASTE_YOUR_FOO_SECRET_KEY_ID_HERE
可以在 ~/.aws/credentials 中共存多个具有不同AWS账户凭证的配置文件。
[foo] aws_access_key_id=PASTE_YOUR_FOO_ACCESS_KEY_ID_HERE aws_secret_access_key=PASTE_YOUR_FOO_SECRET_KEY_ID_HERE [bar] aws_access_key_id=PASTE_YOUR_BAR_ACCESS_KEY_ID_HERE aws_secret_access_key=PASTE_YOUR_BAR_SECRET_KEY_ID_HERE
如果指定了 ~/.aws/credentials 中的多个配置文件,您可以通过设置 AWS_PROFILE 环境变量来选择活动配置文件。
export AWS_PROFILE=foo
用法
运行 --help 以显示用法信息。
s3am --help
从FTP服务器上传文件到S3。
s3am upload \ ftp://ftp.1000genomes.ebi.ac.uk/vol1/ftp/data/NA12878/sequence_read/ERR001268.filt.fastq.gz \ s3://foo-bucket/
将结果对象复制到另一个存储桶。
s3am upload \ s3://foo-bucket/ERR001268.filt.fastq.gz \ s3://other-bucket/
将副本下载到本地文件系统。
s3am download \ s3://other-bucket/ERR001268.filt.fastq.gz \ ./
注意,上述所有示例都省略了目标文件名。如果目标以 / 字符结尾,则将源URL的最后一个路径组件(即“文件名”)追加。
如果上传中断,可以通过再次运行带有 --resume 选项的命令来继续上传。要取消未完成的上传,请运行 s3am cancel。请注意,不完整的分片上传将产生存储费用。
故障排除
如果您遇到 错误:[Errno 104] 对等方重置连接,则可能是由于S3AM使用太多的上传槽位或部分大小太低。请注意,默认情况下,S3AM使用保守的小部分大小,但为每个核心分配一个上传槽位。例如,在32核心EC2实例上运行s3am并使用默认的5 MiB部分大小可能会导致每秒超过100次请求,这将触发S3端请求速率限制器,从而导致此特定错误。考虑传递 --part-size=256MB 或 --upload-slots=8。前者是推荐的,因为后者将负面影响您的吞吐量。
优化
默认情况下,S3AM每个核心并行传输一个部分。这是一个非常保守的设置。由于S3AM主要受I/O限制,您应该显著超订核心,可能至少是10倍。例如,在具有8个核心的机器上,您应该使用 --download-slots 40 --upload-slots 40 运行S3AM。
如果您在EC2上运行S3AM,您可能比从源服务器有更多的带宽到S3。在这种情况下,拥有更多的下载槽位比上传槽位可能有所帮助。
默认的分区大小为5MB也非常保守。如果源数据有较高的延迟,您可能需要增加该值,因为TCP窗口增长到最佳大小可能需要一段时间。如果源是ftp://,那么在实际传输开始之前,与http://或https://相比,会有更多的往返。在任何情况下,您可能都需要将分区大小增加到至少50MB。
构建
克隆存储库,创建虚拟环境,激活它并运行make develop
git clone https://github.com/BD2KGenomics/s3am.git cd s3am virtualenv venv venv/bin/activate make develop
加密
在SSE-C中,S3服务器执行实际加密,但客户端提供加密密钥。这比纯SSE更安全,因为SSE-C的密钥加密密钥不会持久化在服务器上,它仅在请求持续的时间内存在于内存中,并在之后被丢弃。SSE-C还允许您公开存储桶并通过加密密钥的分发来控制访问。
脚本
您可以启用恢复并尝试几次
for i in 1 2 3; do s3am upload --resume $src $dst && break; done s3am cancel $dst
有些情况下,恢复是徒劳的,必须小心不要陷入无限循环,这可能会花费无限的资金。S3AM在明显的用户错误上退出状态码为2,但可能有其他需要用户干预的故障,如认证问题。没有可靠的方法将错误分类为可恢复和不可恢复的,因此S3AM甚至不尝试这样做。运行s3am cancel是尽量避免留下未完成的上传的最佳努力。如果s3am upload对某个对象成功,则在那个对象上运行s3am cancel不会做任何事情。
或者,您可以强制S3AM消除先前的、不成功的尝试,创建一个干净的起点,防止它们破坏当前的尝试。但这会以浪费先前的尝试所取得的进度为代价
for i in 1 2 3; s3am upload --force $src $dst && break; done s3am cancel $dst
–force和–resume选项互斥,但都提供了一定程度的一致性。虽然--resume在检测到给定S3对象的多个未完成上传时拒绝运行,但--force不那么容易被打消。因此得名。
在Toil脚本中,我会使用--resume选项和一个手动编写的循环,或者使用--force选项并依赖Toil内置的工作重试机制。
注意事项
S3AM还不支持非美国存储桶。请参阅问题#12。
S3AM为每个上传和下载槽使用一个缓冲区。该缓冲区将保留整个分区。这意味着S3AM的内存占用下限是(下载槽位 + 上传槽位) * 分区大小。需要缓冲区,因为S3不支持分块传输编码。
S3AM没有实现连续的校验和。为上传到S3的每个分区计算MD5,但没有代码来比较MD5与源端。我认为S3公开了所有部分MD5的串联MD5。因此,如果我们能够使libcurl和发送服务器支持Content-MD5 HTTP头,我们可以使用它。但这不会像在整个文件上验证MD5那样提供强有力的保证。
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。