curl--parallel-immediate选项详解:并行传输时优先新建连接而非等待多路复用
【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl
--parallel-immediate是 curl 命令行工具在并行传输(--parallel/-Z)模式下用于调整连接调度策略的开关。开启后,curl 会倾向于为每个新传输直接建立独立连接,而不是像默认行为那样先等待片刻、尝试把新传输复用到已有多路复用(HTTP/2 与 HTTP/3)连接上。本文结合 curl 仓库中的命令行解析、并行调度与连接复用源码,完整讲解该选项的行为机制、底层实现、适用场景与配套参数。
选项总览
该选项在 curl 中属于"连接(connection)"类别的全局布尔选项,从 7.68.0 版本开始提供。其完整定义位于 docs/cmdline-opts/parallel-immediate.md:
- 长选项:
--parallel-immediate - 短选项:无
- 帮助文本:Do not wait for multiplexing(不等待多路复用)
- 添加版本:7.68.0
- 分类:connection curl global
- 是否可重复:boolean(开关型,可与
--no-parallel-immediate反向使用) - 作用域:global(全局生效)
它是--parallel(-Z)并行传输模式的辅助开关,单独使用没有任何效果;只有配合--parallel一起使用才有意义。官方给出的典型用法是:
curl --parallel-immediate -Z $URL -o file1 $URL -o file2默认行为:倾向于等待并复用多路复用连接
要理解--parallel-immediate,必须先理解 curl 并行传输的默认连接策略。
在没有该选项时,当 curl 以--parallel模式同时发起多个传输(默认最多 50 个并发,见 docs/cmdline-opts/parallel.md 与--parallel-max),它并不急于为每一个 URL 都建立全新的 TCP/TLS 连接,而是优先考虑复用:
- 对每个待发起的传输,先在连接池(connection pool)中查找指向同一目标(destination)的既有连接;
- 如果找到的连接已经具备多路复用能力(例如通过 ALPN 协商出的 HTTP/2、HTTP/3),就把新传输作为一条新 stream 挂到该连接上;
- 如果找到的是正在连接中(pending)的候选连接,并且设置了
CURLOPT_PIPEWAIT,curl 会等待一小段时间,观察该连接能否协商出多路复用能力,再决定复用还是新建。
这种策略的好处是把连接数量压到最低——大量传输共享少量连接,减少握手开销与服务器连接数。代价是:新传输的启动可能会有轻微延迟,因为它要为"等待多路复用机会"付出等待时间。
--parallel-immediate的行为:放弃等待,立即新建连接
--parallel-immediate恰恰是对上述等待行为的反制。开启后,curl 在并行传输时更倾向于立刻打开新的并行连接,而不是停下来等待观察新传输能否搭上另一条连接的多路复用流。
从效果上看,这是"连接数量"与"启动速度"之间的权衡:
- 默认(不加该选项):连接数少,但对复用不确定的连接会等待,传输启动可能稍慢;
- 开启
--parallel-immediate:传输启动更快、更果断,但同一时刻打开的连接数可能显著增多。
源码实现:从命令行开关到连接调度的完整链路
1. 命令行解析与状态存储
选项在 src/tool_getparam.c 中注册为布尔参数,解析后写入全局配置结构:
{"parallel-immediate", ARG_BOOL, ' ', C_PARALLEL_IMMEDIATE},对应处理分支(src/tool_getparam.c):
case C_PARALLEL_IMMEDIATE: /* --parallel-immediate */ global->parallel_connect = toggle; break;该布尔标志parallel_connect定义在全局配置结构 src/tool_cfgable.h 中:
BIT(parallel); BIT(parallel_connect);parallel_connect这个名字直观地表达了选项本质:让并行传输直接去"连接"(connect),而不要等待。
2. 关键生效点:关闭 PIPEWAIT
真正决定调度行为的是并行调度器在把每个 easy handle 加入 multi 句柄之前设置的CURLOPT_PIPEWAIT。在 src/tool_operate.c 的add_parallel_transfers()中有明确的实现注释:
/* parallel connect means that we do not set PIPEWAIT since pipewait makes libcurl prefer multiplexing */ (void)curl_easy_setopt(per->curl, CURLOPT_PIPEWAIT, global->parallel_connect ? 0L : 1L);这段代码直接揭示了两个模式的核心差异:
- 未开启
--parallel-immediate:parallel_connect为 0,于是每个传输设置CURLOPT_PIPEWAIT = 1L。libcurl 在找不到可用复用连接时,会等待可能的复用机会(见下节); - 开启
--parallel-immediate:parallel_connect为 1,于是CURLOPT_PIPEWAIT = 0L,传输不再为多路复用等待,直接新建连接。
3. PIPEWAIT 在连接池中的语义
CURLOPT_PIPEWAIT是 libcurl 库层面的选项(注册于 lib/easyoptions.c)。它的作用体现在连接池查找逻辑中:在 lib/url.c 的url_match_result()里,当连接池中存在"正在连接中的候选连接(pending connection)"且设置了 PIPEWAIT 时,libcurl 会决定等待:
else if(match->seen_pending_conn && match->data->set.pipewait) { infof(match->data, "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set"); match->wait_pipe = TRUE; }wait_pipe置真意味着:本次传输先不新建连接,而是挂起等待那条 pending 连接完成握手——如果它协商出 HTTP/2/3 多路复用能力,就把传输作为新 stream 复用到其上;如果对方不支持复用,再回退为新建连接(代码中同样处理了"已见 single-use 连接且未见 multiplex 连接"即服务器不支持复用的情形,见 lib/url.c)。
因此,--parallel-immediate通过关闭 PIPEWAIT,从根源上跳过了"等待 pending 连接判定复用能力"这一环节,让每个传输立刻走新建连接路径。
4. 与并发上限的联动
并行传输的调度在 src/tool_operate.c 的add_parallel_transfers()中完成:它根据global->parallel_max(由--parallel-max控制,默认 50)决定同时挂载到 multi 句柄上的 easy handle 数量,已有传输结束时再补充新的。--parallel-immediate影响的是这些传输"如何获取连接",而--parallel-max决定"同时允许多少传输在跑",两者相互独立、可自由组合。
从源码结构可以推断:开启--parallel-immediate后,由于放弃复用等待,同一时刻向同一目标建立的连接数会明显高于默认模式,因此它更适合"快速启动优先、连接数不敏感"的场景。
典型使用场景
结合上述机制,以下场景适合使用--parallel-immediate:
- 对启动延迟敏感的场景:例如需要尽快发出所有请求的监控、探测类脚本,不希望任何传输因为等待复用判定而延后;
- 目标服务器不支持或难以协商 HTTP/2 多路复用:如果服务器每次握手才能确定是否支持复用,等待往往只是浪费时间,直接连接更快;
- 同一目标上的传输彼此独立:传输间没有共享连接带来的收益时,直接并行建连更省事;
- 配合多目标混合下载:如官方示例那样同时对多个 URL 发起下载,希望每个 URL 都立即获得独立连接:
curl --parallel-immediate -Z \ https://example.com/file1.bin -o file1.bin \ https://example.com/file2.bin -o file2.bin \ https://example.net/file3.bin -o file3.bin反之,以下场景则应保持默认(不要加该选项):
- 目标服务器支持 HTTP/2/3 多路复用,且希望尽量少占用连接资源、降低服务器连接压力;
- 大量 URL 指向同一主机,复用连接能显著减少 TLS 握手开销;
- 连接数受服务器或网络设备限制,需要严格控制并发连接数量。
配套参数一览
--parallel-immediate通常与以下全局并行参数配合使用(定义均位于 docs/cmdline-opts 目录):
| 选项 | 作用 | 说明 |
|---|---|---|
-Z, --parallel | 启用并行传输 | 并行模式的开关,--parallel-immediate的前置条件 |
--parallel-max <num> | 最大并发传输数 | 默认 50,详见 docs/cmdline-opts/parallel-max.md |
--parallel-max-host <num> | 单主机最大并发传输数 | 限制指向同一主机的并行传输数量,见 src/tool_getparam.c |
--parallel-immediate | 不等待多路复用,优先新建连接 | 本文主题 |
在curl --help all的输出中,这些选项位于并行传输分组内,注册于 src/tool_listhelp.c。另外,--parallel-immediate是布尔开关,因此也支持--no-parallel-immediate形式用于脚本中覆盖先前设置。
注意事项与版本边界
- 必须配合
--parallel:该选项只影响并行传输模式的连接调度,串行传输(默认模式)下无效; - 最低版本 7.68.0:低于该版本的 curl 无法识别该选项,脚本跨版本使用时建议先用
curl --version确认; - 与
--parallel-max-host联用:如果既想快速建连、又需要限制单主机连接数,可将--parallel-immediate与--parallel-max-host组合,避免对同一服务器打爆连接; - 网络开销上升:开启后不再等待复用,同一目标的连接数可能成倍增长,TLS 握手、TCP 建连的系统开销相应增加,适合内网或低延迟环境,公共大流量环境下需评估服务器承载能力;
- 行为判定依赖 ALPN/HTTP 版本:多路复用能力只有在连接握手(如 ALPN 协商)后才能确定,这正是默认模式下"等待"存在的根本原因;
--parallel-immediate则彻底跳过这一等待阶段。
小结
--parallel-immediate本质上是 curl 并行传输调度中"连接复用等待"策略的开关:默认开启等待(通过CURLOPT_PIPEWAIT让传输等待 pending 连接的复用机会),开启该选项后则关闭等待、为每个传输立即建立独立连接。从 src/tool_operate.c 的实现可见,它最终只是把每个 easy handle 的CURLOPT_PIPEWAIT置为 0。理解这一机制后,你可以在"连接数最少"与"启动最快"两种策略间按需切换,让-Z并行下载在合适的场景发挥最大效率。
【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考