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

如何在Bash脚本中并行化curl调用,测量P2P节点数据同步耗时

并行化检测P2P数据块节点同步耗时的优化方案

你的串行检测方案存在两个核心问题:一是检测效率极低,必须等待前一个节点请求完成才能检测下一个;二是时间测量偏差——后检测的节点可能早已完成同步,但因为串行等待的延迟,会导致你统计的"全部节点同步耗时"远大于实际值。

下面提供几种无需额外复杂依赖的并行化实现方案,解决上述问题:

方案一:Bash后台进程+Wait(原生无依赖)

利用Bash的后台任务(&)和wait命令实现全并行检测,同时通过临时文件收集每个节点的检测结果,确保所有请求完成后统一统计状态。

# 记录检测起始时间(需与数据块分发开始时间对齐)
start_time=$(date +%s.%N)

# 计算总节点数
total_nodes=$(( ${#BOXES[@]} * NODE_PER_BOX ))
# 定义节点基础端口(根据你的实际配置修改)
BASE_PORT=8080

while :; do
    echo "正在检测节点同步状态..."
    synced_count=0
    # 创建临时文件存储单节点检测结果
    temp_result=$(mktemp)

    # 并行发起所有节点的检测请求
    for box in "${BOXES[@]}"; do
        for ((j=0; j<NODE_PER_BOX; j++)); do
            node_url="http://${box}:$((BASE_PORT + j))/api"
            # 后台执行curl,检测到目标数据则标记为1,否则0,写入临时文件
            (curl -s -m 3 "$node_url" | grep -q "目标数据特征字符串" && echo "$box:$j:1" || echo "$box:$j:0") >> "$temp_result" &
        done
    done

    # 等待所有后台检测任务完成
    wait

    # 统计已同步节点数量
    while IFS=: read -r _ _ status; do
        [ "$status" -eq 1 ] && ((synced_count++))
    done < "$temp_result"

    rm "$temp_result"

    # 检查是否所有节点完成同步
    if [ "$synced_count" -eq "$total_nodes" ]; then
        end_time=$(date +%s.%N)
        # 计算耗时(保留3位小数)
        elapsed=$(printf "%.3f" $(echo "$end_time - $start_time" | bc -l))
        echo "所有节点已完成同步,总耗时:${elapsed}秒"
        break
    fi

    # 检测间隔(避免频繁请求,可根据需求调整)
    sleep 0.5
done

关键细节:

  • 添加-m 3给curl设置3秒超时,避免单个节点无响应阻塞整个检测流程
  • 目标数据特征字符串需替换为API返回中标识数据块存在的内容(比如特定JSON字段、关键词)
  • 起始时间需与数据块开始分发的时间点对齐,确保耗时统计准确

方案二:Xargs并行批量处理

利用xargs的-P参数指定并行进程数,批量发起检测请求,适合快速实现轻量并行。

start_time=$(date +%s.%N)
total_nodes=$(( ${#BOXES[@]} * NODE_PER_BOX ))
BASE_PORT=8080

# 生成所有节点的检测URL列表
generate_node_urls() {
    for box in "${BOXES[@]}"; do
        for ((j=0; j<NODE_PER_BOX; j++)); do
            echo "http://${box}:$((BASE_PORT + j))/api"
        done
    done
}

while :; do
    echo "正在检测节点同步状态..."
    # 并行发起所有请求,统计符合条件的响应数
    synced_count=$(generate_node_urls | xargs -P "$total_nodes" -I {} curl -s -m 3 {} | grep -c "目标数据特征字符串")

    if [ "$synced_count" -eq "$total_nodes" ]; then
        end_time=$(date +%s.%N)
        elapsed=$(printf "%.3f" $(echo "$end_time - $start_time" | bc -l))
        echo "所有节点已完成同步,总耗时:${elapsed}秒"
        break
    fi

    sleep 0.5
done

优势:

  • 代码更简洁,无需手动管理后台进程和临时文件
  • -P参数可灵活控制并行数(比如服务器性能有限时,可设置为-P 10限制10个并行进程)

方案三:GNU Parallel(功能更强大)

如果系统允许安装工具,parallel是更专业的并行任务管理工具,支持多参数传递、任务失败重试等高级功能。

start_time=$(date +%s.%N)
total_nodes=$(( ${#BOXES[@]} * NODE_PER_BOX ))
BASE_PORT=8080

# 定义单个节点检测函数
check_node() {
    box=$1
    node_idx=$2
    node_url="http://${box}:$((BASE_PORT + node_idx))/api"
    # 检测成功返回0,失败返回1
    curl -s -m 3 "$node_url" | grep -q "目标数据特征字符串"
}

# 导出函数和变量,供parallel使用
export -f check_node
export BASE_PORT

while :; do
    echo "正在检测节点同步状态..."
    # 并行执行检测,统计成功的任务数
    synced_count=$(parallel -j "$total_nodes" check_node ::: "${BOXES[@]}" ::: $(seq 0 $((NODE_PER_BOX -1))) | wc -l)

    if [ "$synced_count" -eq "$total_nodes" ]; then
        end_time=$(date +%s.%N)
        elapsed=$(printf "%.3f" $(echo "$end_time - $start_time" | bc -l))
        echo "所有节点已完成同步,总耗时:${elapsed}秒"
        break
    fi

    sleep 0.5
done

适用场景:

  • 需要对检测任务做更精细控制(比如失败重试、按节点分组)
  • 节点参数复杂,需要多参数传递给检测逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 16:55:20