Skip to content

Latest commit

 

History

History
 
 

serverless

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Amazon S3 MultiThread Resume Migration Serverless Solution (Amazon S3 多线程断点续传迁移无服务器方案)

Serverless Version ENGLISH README

Cluster & Serverless Version 0.98

无服务器版本

Amazon EC2 Autoscaling Group Cluster and Serverless AWS Lambda can be deployed together, or seperated used in different senario
AmazonEC2自动扩展集群版本和无服务器Lambda版本,可以分别单独部署和运行在不同场景,也可以一起运行。

  • 海外和国内AmazonS3互传:无服务器版适合不定期突发传输。

  • 配合Amazon SQS超时时间,AWS Lambda 同样可以支撑单文件几十GB级别的对象,不用担心15分钟超时。

  • 快速且稳定:多AWS Lambda并发 X 单个Lambda runtime并发多线程,支撑海量巨型文件并发传输。自动区分小文件(包括 0 Size 文件)和大文件,走不同流程。

  • 对于特殊区域,需要指定IP或必须启用BBR的场景,可以配置Lambda VPC模式,经NAT Instance访问互联网

  • 可靠:Amazon SQS消息队列管理文件级任务,断点续传,超时中断保护。每个分片MD5完整性校验。Single Point of True,最终文件合并以S3上的分片为准,确保分片一致。

  • 安全:内存转发不写盘,传输SSL加密,开源代码可审计,采用IAM Role和Lambda环境变量加密存储AcceesKey。

  • 可控运营:任务派发与传输速度相匹配,系统容量可控可预期;Amazon DynamoDB和SQS读写次数只与文件数相关,而与文件大小基本无关;日志自动收集;

  • 弹性成本优化:无服务器AWS Lambda只按调用时长*次数计费;支持直接存入S3各种存储级别,节省长期存储成本。

    无服务器版架构图如下:
    Amazon S3 新增文件触发传输:  Diagram New created object in S3

    Jobsender 扫描 Amazon S3 派发传输任务:  Diagram Jobsender scan buckets
    CloudWatch Event 定时任务每小时触发一次 Jobsender 运行

性能实测

  • 美国Virginia AWS Lambda(不经NAT)1310个 文件(共50GB)文件大小从4M到1.3GB不等。 10分钟完成传输到中国宁夏Region。最高时153并发Lambda Runtime。文件成倍增大,传输时间并没有成倍增加。每个文件由一个Lambda并发独立处理,文件大,每个分片5MB,Lambda runtime 内就自动更多的Threads在并行传输。Lambda 内存配置 1GB,根据文件大小的情况,可以进一步调整缩小Lambda配置到最合适到性价比。

性能实测

  • 日本Tokyo: AWS Lambda(经VPC NAT Instance,NAT配置EIP地址和TCP BBR)单个80GB video文件,和单个45GB zip文件,分别 2 到 6 小时不等的时间传到中国宁夏region。是单文件由单并发Lambda Runtime处理。

AWS Lambda 15分钟运行超时后,Amazon SQS消息InvisibleTime超时,消息恢复,重新触发一个Lambda runtime,从S3获取已上传分片列表,并继续传后续的分片。以下是log日志截图:

大文件断点自动续传

  1. AWS Lambda获取目标Amazon S3的 upload id列表,获得最后一次上传记录
  2. 获取分片列表
  3. 如出现网络中断,自动延迟重试
  4. 获得目标Amazon S3上的已上传分片列表
  5. 自动匹配分片号码
  6. 下载剩下未上传的分片

自动部署监控 Dashboard

dashboard

CDK 自动化部署

请先安装 AWS CDK 然后由 CDK部署。CDK 文档可参照官网:
https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html

1. 前置配置

  • 请在 AWS CDK 部署前手工配置 System Manager Parameter Store 新增这个参数
    名称:s3_migration_credentials
    类型:SecureString
    级别:Standard
    KMS key source:My current account/alias/aws/ssm 或选择其他你已有的加密 KMS Key
    这个 s3_migration_credentials 是用于访问跟 AWS Lambda 不在一个账号系统下的那个S3桶的访问密钥,在目标Account 的IAM user配置获取。配置示例:
{
  "aws_access_key_id": "your_aws_access_key_id",
  "aws_secret_access_key": "your_aws_secret_access_key",
  "region": "cn-northwest-1"
}

配置示意图:
配置示意图

  • 配置 AWS CDK 中 app.py 你需要传输的源S3桶/目标S3桶信息,示例如下:
[{
    "src_bucket": "your_global_bucket_1",
    "src_prefix": "your_prefix",
    "des_bucket": "your_china_bucket_1",
    "des_prefix": "prefix_1"
    }, {
    "src_bucket": "your_global_bucket_2",
    "src_prefix": "your_prefix",
    "des_bucket": "your_china_bucket_2",
    "des_prefix": "prefix_2"
    }]

这些会被AWS CDK自动部署到 System Manager Parameter Store 的 s3_migration_bucket_para

2. CDK自动部署

./cdk-serverless 该 CDK 由 Python 编写,会自动部署以下所有资源:

  • Option1: 新建了一个 Amazon S3 Bucket,这个Bucket所有新增的文件都会触发SQS,从而触发Lambda进行传输。
    如果你的 Bucket 是现有的,则可以手工配置这个Bucket触发SQS。
  • Option2: 如果你没有权限配置现有的Bucket去触发SQS,例如别人的 Bucket 只开放了读权限给你,则本CDK部署 Lambda Jobsender 定时任务去扫描这些 Bucekt,并生成传输任务给 Lambda Worker 去执行。你只需要在 CDK 中的 app.py 配置对应的 Bucekts 信息即可。
  • CDK 新建了 Amazon SQS Queue 队列和 一个相应的 SQS Queue DLQ 死信队列。InVisibleTime 15 分钟,有效期 14 天,重试 60 次后送 DLQ
  • 新建 Amazon DynamoDB 表
  • 上传 AWS Lambda 代码并配置函数相关参数,配置 AWS Lambda 的运行超时时间 15 分钟,内存 1GB,自动配置 AWS Lambda 访问 S3,SQS 和 DynamoDB 的 IAM 权限。Lambda 函数有两个:Jobsender 和 Worker。一个由CloudWatch Evnet 定时任务触发,负责根据Bucket信息扫描S3,生成任务发给SQS;一个是由SQS触发去传输S3上的对象。
  • AWS CDK 会新建一个 CloudWatch Dashboard: s3_migrate_serverless 监控 SQS 消息和 Lambda 运行状态
  • 通过 AWS Lambda Log Group 创建了三个自定义 Log Filter,过滤出 Uploading, Downloading, Complete 的分片 Bytes,并统计为 Lambda 流量发布到 Dashboard。另外还创建了两个 Filter 监控日志出现 WARNING 或 ERROR。
  • Ignore List: Jobsender 可以支持忽略某些文件,或者某类型文件 (通配符*或?),不生成SQS任务。请在CDK目录的s3_migration_ignore_list.txt中配置。CDK部署的时候会将该列表上传到 SSM Parameter Store,你也可以后续在 parameter store 修改这个参数 s3_migrate_ignore_list。配置示例:
your_src_bucket/your_exact_key.mp4
your_src_bucket/your_exact_key.*
your_src_bucket/your_*
*.jpg
*/readme.md

手工配置说明

如希望手工部署,则注意以下几点:

  • 配置 Amazon SQS Access Policy,允许S3 bucket发布消息。修改以下json中account和bucket等信息:
{
  "Version": "2012-10-17",
  "Id": "arn:aws:sqs:us-east-1:your_account:s3_migrate_file_list/SQSDefaultPolicy",
  "Statement": [
    {
      "Sid": "Sidx",
      "Effect": "Allow",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Action": "SQS:SendMessage",
      "Resource": "arn:aws:sqs:us-east-1:your_account:s3_migrate_file_list",
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:s3:::source_bucket"
        }
      }
    }
  ]
}
  • 对 AWS Lambda 的 log group 创建三个 Log filter,匹配 Pattern 如下:
Namespace: s3_migrate
Filter name: Downloading-bytes
Pattern: [info, date, sn, p="--->Downloading", bytes, key]
Value: $bytes
default value: 0
Filter name: Uploading-bytes
Pattern: [info, date, sn, p="--->Uploading", bytes, key]
Value: $bytes
default value: 0
Filter name: Complete-bytes
Pattern: [info, date, sn, p="--->Complete", bytes, key]
Value: $bytes
default value: 0

这样就把 AWS Lambda 的流量统计到了自定义 Metric s3_migrate,可以在 CloudWatch Metric 监控了。把监控配置为统计方式:Sum,周期 1 分钟。

S3 版本控制支持

为什么要启用 S3 版本控制

如果不启用S3版本控制,在大文件正在传输的过程中,如果此时原文件被新的同名文件替换,会导致复制的文件部分是老的文件,部分是新的文件,从而破坏了文件的完整性。以前做法是强调不要在传输过程中去替换源文件,或者只允许新增文件。
而对于无法避免会覆盖源文件的场景下,可以启用S3版本控制,则可以避免破坏文件完整性的情况。本项目已支持S3版本控制,需要配置:

  • 对源文件的S3桶“启用版本控制”(Versioning)
  • 源S3桶必须开放 ListBucketVersions, GetObjectVersion 这两个权限
  • 以及设置以下的配置参数,分不同场景说明如下

支持S3 版本控制的配置参数

  • JobsenderCompareVersionId(True/False):
    Jobsender 在对比S3桶的时候,对源桶获取对象列表时同时获取每个对象的 versionId,来跟目标桶比对。目标桶的 versionId 是在每个对象开始下载的时候保存在 DynamoDB 中。Jobsener 会从 DynamoDB 获取目标桶 versionId 列表。Jobsender发给SQS的Job会带上versionId。默认 Flase。

  • UpdateVersionId(True/False):
    Worker 在开始下载源文件之前是否更新Job所记录的versionId。这功能主要是面向 Jobsender 并没有送 versionId 过来,但又需要启用 versionId 的场景。默认 Flase。

  • GetObjectWithVersionId(True/False):
    Worker 在获取源文件的时候,是否带 versionId 去获取。如果不带 versionId 则获取当前最新文件。
    默认 Flase。

对于Cluster版本,以上参数都在配置文件 s3_migration_config.ini 对于Serverless版本,以上参数分别在 Lambda jobsender 和 worker 的环境变量中

场景

  • S3新增文件触发的SQS Jobs:
  UpdateVersionId = False  
  GetObjectWithVersionId = True   

S3新增文件直接触发SQS的情况下,S3启用了版本控制功能,那么SQS消息里面是带 versionId 的,Worker 以这个versionId 去 GetObject。如果出现中断,恢复时仍以该 versionId 去再次获取。 如果你没有GetObjectVersion权限,则需要把这两个开关设False,否则会因为没权限而获取文件失败 (AccessDenied)。

  • Jobsender比对S3发送SQS Jobs这里又分两种目的:

    1. 完整性:为了绝对保证文件复制过程中,即使被同名文件覆盖,也不至于文件半新半旧。
    JobsenderCompareVersionId = False  
    UpdateVersionId = True  
    GetObjectWithVersionId = True  
    

    为了比对速度更快,所以在比对的时候不获取versionId,这样发送SQS的 versionId 是 'null' 在 Get object 之前获取真实 versionId,并写入 DynamoDB,完成传输之后对比DDB记录的 versionId 。在文件传输结束时,再次校验 DynamoDB 中保存的 versionId,如果因为发生中断重启,而刚好文件被替换,此时versionId会不一致,程序会重新执行传输。

    1. 完整性和一致性:为了对比现存源和目的S3的文件不仅仅Size一致,版本也要一致性。并绝对保证文件复制过程中,即使被同名文件覆盖,也不至于文件半新半旧。
    JobsenderCompareVersionId = True  
    UpdateVersionId = False  
    GetObjectWithVersionId = True  
    

    Jobsender会比对 versionId,并且发送SQS带真实 versionId。此时已经有真实的 versionId了,就没必要启用worker UpdateVersionId了,节省时间和请求数。

  • 对于觉得没必要比对文件 version,文件传输过程中也不会被替换,或者没有源S3的 GetObjectVersion 权限,则三个开关都设置False即可(默认情况)

为什么不默认就把所有开关全部打开

  • 速度问题:获取源S3 List VersionId 列表,会比只获取 Object 列表慢的多,如果文件很多(例如1万条记录以上),又是 Lambda 做 Jobsender 则可能会超过15分钟限制。

  • 权限问题:不是所有桶都会开放 GetObjectVersion 权限。例如某些 OpenDataSet 即使打开了 Versioning 功能,但却没有开放 GetObjectVersion 权限。

局限和提醒注意:

  • 所需内存 = 并发数 * ChunckSize 。小于50GB的文件,ChunckSize为5MB,大于50GB的文件,则ChunkSize会自动调整为约等于: 文件Size/10000。
    例如如果平均要处理的文件 Size 是 500GB ,ChunckSize 会自动调整为50MB,并发设置是 5 File x 10 Concurrency/File = 50,所以需要的EC2或Lambda的可运行内存约为 50 x 50MB = 2.5GB。 如需要提高并发度,可以调整配置,但对应的EC2或Lambda内存也要相应增加。

  • 不要在开始数据复制之后修改Chunksize。

  • Jobsender 只对比文件 Bucket/Key 和 Size。即相同的目录下的相同文件名,而且文件大小是一样的,则会被认为是相同文件,jobsender或者单机版都会跳过这样的相同文件。如果是S3新增文件触发的复制,则不做文件是否一样的判断,直接复制。

  • 删除资源则 cdk destroy 。
    另外 DynamoDB、CloudWatch Log Group 、自动新建的 S3 bucket 需要手工删除

License

This library is licensed under the MIT-0 License. See the LICENSE file.