排查FIFO容量限制:S3对象迁移脚本仅处理7000个任务
环境信息
- 操作系统:
CentOS 7.9 - Bash版本:
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
背景
通过Shell脚本(调用curl访问本地MinIO端点)进行S3对象迁移。脚本通过后台进程&启动多个工作进程,使用FIFO作为任务队列,借助flock控制队列读取,完成对象的下载、上传等操作。脚本部分代码如下:
# ... # 读取参数、显示信息 ... # 设置锁、FIFO ... # 定义工作进程执行的job()函数。 # # ... # FIFO(任务队列)为文件描述符3 # FIFO锁为文件描述符4 function work () { wid=$1 # 设置文件描述符和锁 # ... while true; do flock 4 # 获取FIFO锁 read -r -su 3 job_id obj read_status=$? flock -u 4 # 释放FIFO锁 if [[ $read_status -eq 0 ]]; then # 若从队列读取到任务,在子进程中执行 fi done # 清理文件描述符 } echo "启动工作进程..." for ((i=1;i<="${WORKERS:-4}";i++)); do printf "%s" "_" work $i & done echo function append_job() { job_id=$1 target_object=$2 printf "\r(%d s) 添加任务 [# %s] %.110s\e[K" "$(( $(date +%s) - ts_start ))" "${job_id}" "${target_object}" echo "${job_id}" "${target_object}" 1>&3 } while read -r obj_name ; do append_job $i "${obj_name}" i=$((i+1)) done < <(the_function_that_list_all_objects_from_bucket ${TARGET_BUCKET}) echo
遇到的问题
脚本处理对象数少于7000的存储桶时正常,但当存储桶对象超过7000个时,仅能添加恰好7000个任务,工作进程仅迁移7000个对象就结束。
预期结果与初步猜想
脚本应无问题完成全部(超过7000个)迁移任务,初步猜想:
- 传入while循环的标准输入(
<(the_function_that_list_all_objects_from_bucket ${TARGET_BUCKET}))会将所有对象列表存储在内存中,暂时与FIFO无关。 - 即使FIFO存在最大容量限制,当工作进程从FIFO读取任务后,FIFO容量应会减少,循环可继续添加任务。
- 即使标准输入非常庞大(如
<(gen_huge_result),超过16GB),操作系统会处理,循环仍能运行,仅耗时更长。
已尝试的操作
检查对象列表的长度和大小:
# the_function_that_list_all_objects_from_bucket ${TARGET_BUCKET} | wc -l 8043 # the_function_that_list_all_objects_from_bucket ${TARGET_BUCKET} | wc -c 434387
通过命令查看管道最大容量:
# cat /proc/sys/fs/pipe-max-size 1048576
8043个对象的迁移理论上不存在问题,还尝试强制减慢任务添加速度,但仍在7000个任务时停止,猜测是任务添加时达到了FIFO的最大容量,但不清楚具体原因。
更新
1. 部分实验
根据建议进行以下实验:
- 是字节限制还是行数限制?
将任务参数增加至4倍:
work() { # ... while true; do ## 尝试读取队列 flock 4 # 获取FIFO锁 read -r -su 3 work_id work_item tmp1 tmp2 tmp3 tmp4 tmp5 tmp6 # 读取到work_id和work_item read_status=$? # 保存read的退出状态 # ... } append_job() { # ... echo "${work_id}" "$work_item" "${work_id}" "$work_item" "${work_id}" "$work_item" "${work_id}" "$work_item" 1>&3 ## FIFO为文件描述符3 }
结果任务数超过了2000,手动执行CTRL+C终止。如果是行数限制,任务数应在约1750(7000/4)时停止。
- 是否存在异常任务?
未发现异常任务,任务执行无标准错误输出,甚至将任务设置为仅执行true,问题仍存在,认为是任务发送环节存在某些限制。
2. 今日无法复现该问题
使用“移动”方式(复制后删除)代替仅“复制”完成了昨日的迁移工作。请求运维团队恢复了迁移开始前的虚拟机快照,再次运行相同脚本,发现任务添加数达到了8043个。推测是重启(恢复镜像)清除了操作系统的某些限制,目前无法复现问题,若再次遇到将尝试相关脚本排查根因。
内容的提问来源于stack exchange,提问作者ktc
相关产品推荐
相关产品推荐

