You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过AWS EMR并行化curl拉取大文件至AWS S3

方案可行性与简单实现方法

这个并行分片拉取+S3合并的方案完全可行,是大文件跨网络传输加速的典型思路,下面给你具体的落地步骤:

1. 先确认源文件支持Range请求

首先要验证目标下载链接支持分片拉取,用curl发送HEAD请求:

curl -I "https://download-link-address/"

检查响应头里是否包含Accept-Ranges: bytes,如果有,说明可以用Range header分片拉取;如果没有,这个方案就无法使用,得换其他方式。

同时顺便获取文件总大小,从Content-Length字段拿到总字节数:

FILE_SIZE=$(curl -I "https://download-link-address/" | grep -i Content-Length | awk '{print $2}' | tr -d '\r')

2. 规划分片规则

设定每个分片的大小,比如选1GB(1073741824字节)——这个大小符合S3分块上传的要求(单分块5MB-5GB),能平衡并行效率和开销。计算总分片数:

PART_SIZE=$((1024*1024*1024))
TOTAL_PARTS=$(( (FILE_SIZE + PART_SIZE - 1) / PART_SIZE ))

3. EMR集群并行拉取分片

不用搭建复杂的Spark/Hadoop作业,直接用EMR的集群节点跑并行Shell任务即可:

方式一:用xargs并行执行(简单快捷)

在EMR主节点上生成所有分片拉取的命令,保存到tasks.txt:

> tasks.txt
for ((i=0; i<TOTAL_PARTS; i++)); do
  START=$((i*PART_SIZE))
  if [ $i -eq $((TOTAL_PARTS-1)) ]; then
    END=$((FILE_SIZE-1))
  else
    END=$(((i+1)*PART_SIZE - 1))
  fi
  echo "curl -H \"Range: bytes=$START-$END\" \"https://download-link-address/\" | aws s3 cp - s3://aws-bucket/temp-parts/part-$i" >> tasks.txt
done

然后用xargs指定并行数执行(比如10个并行任务,根据集群带宽和源服务器承受能力调整):

cat tasks.txt | xargs -P 10 -I {} sh -c {}

如果需要弹性扩容,可以给EMR集群添加Task节点,然后提高xargs的-P值,加快拉取速度。

方式二:用EMR Steps批量执行(更可控)

如果需要更规范的任务管理,可以把分片命令做成EMR Step,每个分片对应一个Step,或者用Step的Shell脚本批量生成任务。不过对于简单场景,xargs足够用了。

4. 合并S3分片到目标文件

方法一:用S3分块上传API(推荐)

这种方法直接利用S3的分块上传机制,不需要额外的合并计算,效率最高:

  1. 初始化分块上传:
UPLOAD_ID=$(aws s3api create-multipart-upload --bucket aws-bucket --key data-file --query 'UploadId' --output text)
  1. 循环上传每个分片作为分块,记录每个分块的ETag:
> parts.json
for ((i=0; i<TOTAL_PARTS; i++)); do
  ETag=$(aws s3api upload-part --bucket aws-bucket --key data-file --part-number $((i+1)) --body s3://aws-bucket/temp-parts/part-$i --upload-id $UPLOAD_ID --query 'ETag' --output text)
  echo "{\"PartNumber\": $((i+1)), \"ETag\": $ETag}" >> parts.json
done
# 整理成S3要求的JSON格式
sed -i '1s/^/[\n/; $s/$/\n]/' parts.json
sed -i '$!s/$/,/' parts.json
  1. 完成分块上传:
aws s3api complete-multipart-upload --bucket aws-bucket --key data-file --upload-id $UPLOAD_ID --multipart-upload file://parts.json
  1. 清理临时分片:
aws s3 rm s3://aws-bucket/temp-parts/ --recursive

方法二:直接合并分片(适合分片数少的场景)

如果分片不多,可以直接在EC2/EMR节点上合并后上传:

# 按顺序合并所有分片并上传
cat $(for i in $(seq 0 $((TOTAL_PARTS-1))); do echo <(aws s3 cp s3://aws-bucket/temp-parts/part-$i -); done) | aws s3 cp - s3://aws-bucket/data-file
# 清理临时分片
aws s3 rm s3://aws-bucket/temp-parts/ --recursive

额外优化点

  • 断点续传:在生成任务时,先检查S3中对应的分片是否存在,存在就跳过,避免重复拉取:
    if ! aws s3 ls s3://aws-bucket/temp-parts/part-$i > /dev/null 2>&1; then
      echo "curl -H \"Range: bytes=$START-$END\" \"https://download-link-address/\" | aws s3 cp - s3://aws-bucket/temp-parts/part-$i" >> tasks.txt
    fi
    
  • 成本控制:EMR集群可以用按需实例+Spot实例的组合,任务完成后及时终止集群,或者只保留主节点,Task节点按需添加/释放。
  • 并行数调整:根据源服务器的带宽限制和EMR集群的网络能力调整xargs -P的数值,避免触发源服务器的限流,或者集群带宽饱和。

内容的提问来源于stack exchange,提问作者Doug MacArthur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 18:53:20