ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

curl 限速指南:使用 `--limit-rate` 精确控制上传与下载带宽

2026/9/10 3:03:43 拓冰建站 浏览量
curl 限速指南:使用 `--limit-rate` 精确控制上传与下载带宽 curl 限速指南使用--limit-rate精确控制上传与下载带宽【免费下载链接】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--limit-rate是 curl 命令行工具中用于限制传输速率的核心参数它同时作用于下载与上传适用于带宽受限的窄带链路limited pipe或需要避免单个传输占满整条带宽的场景。阅读本文后你将掌握该参数的完整语法含 1024 进制单位后缀与 8.19.0 起支持的小数值、它与--speed-limit/--speed-time/--max-time的协作关系并了解从命令行参数解析到 libcurl 令牌桶token bucket限速引擎的完整底层实现。本文内容以 limit-rate 选项文档为主体结合仓库源码与实际配置展开。选项速览以下元数据取自 limit-rate.md 的文件头是 curl 帮助系统与 man page 的生成来源属性值长选项--limit-rate参数speed帮助文本Limit transfer speed to RATE分类Categoryconnection引入版本Added7.10是否可复用Multisingle单次调用仅生效一次后出现的值覆盖先前的值See-also--rate、--speed-limit、--speed-time--limit-rate的功能与使用场景--limit-rate用于指定 curl 希望使用的最大传输速率且同时约束下载与上传两个方向。文档的原话是Specify the maximum transfer rate you want curl to use - for both downloads and uploads. This feature is useful if you have a limited pipe and you would like your transfer not to use your entire bandwidth.适用场景非常明确当你处于窄带链路上或运行环境要求 curl 的传输不能占满整条带宽时用它可以刻意让传输比默认更慢、更温和To make it slower than it otherwise would be。典型用法包括后台下载大文件时给其他应用留出带宽上传到远端服务器时避免打满上行而影响其他业务在自动化脚本中对每个传输做流控避免瞬时并发冲击。单位语法1024 进制的字节速率默认情况下speed以字节/秒为单位一旦附加后缀则按 1024 进制换算后缀大小写均可含义换算无后缀字节/秒例如1000即 1000 字节/秒k/K千字节1k 1024m/M兆字节1m 1024 × 1024g/G吉字节1024³t/T太字节1024⁴p/P拍字节1024⁵文档原句强调The supported suffixes (k, M, G, T, P) are 1024-based. For example 1k is 1024.也就是说这里没有所谓的商业十进制换算1k严格等于 1024 字节而非 1000。官方给出的示例值包括200K、3m和1G。8.19.0 起支持小数从 curl 8.19.0 开始速率可以用小数指定例如2.5M表示每秒两个半兆字节two and a half megabytes per second。注意两点限制分隔符只能是小写句点.与系统 locale 的偏好无关——即不要使用逗号等形式该语法由命令行解析层支持详见下文 GetSizeParameter解析出的最终值仍是整数字节数。# 每秒 2500 KB2.5 MiB/s级下载 curl --limit-rate 2.5M https://example.com/big.bin基本用法示例原文档给出四个可直接运行的示例覆盖了纯字节、小写/大写后缀、以及限速与超时联用的场景# 1) 小数 后缀约 123.45 KiB/s curl --limit-rate 123.45K $URL # 2) 纯数字无后缀每秒不超过 1000 字节 curl --limit-rate 1000 $URL # 3) 大写后缀每秒不超过 10 MiB curl --limit-rate 10M $URL # 4) 限速 总超时即使 200 KiB/s 也最多只跑 60 秒 curl --limit-rate 200K --max-time 60 $URL示例 4 是两个自我保护型参数的组合--limit-rate让速度不超过阈值--max-time则设定整个操作的最长耗时两者常用于下载场景的上限约束。参数解析实现GetSizeParameter 与 GetParameter命令行层对--limit-rate的解析位于 src/tool_getparam.ccase C_LIMIT_RATE: /* --limit-rate */ err GetSizeParameter(nextarg, value); if(!err) { config-recvpersecond value; config-sendpersecond value; } break;可见一个关键实现细节一次--limit-rate会同时写入recvpersecond与sendpersecond两个字段这正是它同时约束上下行速率的来源。两个字段定义于 src/tool_cfgable.hcurl_off_t sendpersecond; /* send to peer */ curl_off_t recvpersecond; /* receive from peer */真正的数值 单位 小数解析由同一文件中的GetSizeParameter()完成src/tool_getparam.c。该函数与--max-filesize共用其代码注释明确声明We support P, T, G, M and K (case insensitive) suffixes并有对应单元测试代码注释中的 Unit test 1623。其内部要点如下单位查找表getunit()定义了 p/t/g/m/k 五个后缀及各自的十进制位长用于小数部分的对齐换算单位匹配是大小写不敏感的匹配时通过(unit | 0x20)统一转为小写比较解析先读整数部分若紧接着读到.则继续解析小数位curlx_str_number/curlx_str_single小数部分按单位十进制位数换算回字节整数位数超过单位精度时会被修剪计算结果会做溢出防护if(value ((CURL_OFF_T_MAX - add) / mul)) return PARAM_NUMBER_TOO_LARGE;传入的原始参数若是形如123.45K、10M或1000的裸数字都会在这里被换算为以字节为单位的curl_off_t整数。之后src/config2setopts.c 在把配置写回 libcurl 句柄时映射为两个 libcurl 选项my_setopt_offt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, config-sendpersecond); my_setopt_offt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, config-recvpersecond);这意味着--limit-rate命令行参数最终对应到 libcurl 传输层的CURLOPT_MAX_SEND_SPEED_LARGE / CURLOPT_MAX_RECV_SPEED_LARGE两个选项。在 src/config2setopts.c 中还有一处细微优化当recvpersecond非零且小于默认缓冲区大小时会同步调小CURLOPT_BUFFERSIZE避免接收缓冲过大而破坏细粒度限速。底层限速引擎令牌桶算法curl 的限速并不只是每 N 字节睡一会儿而是由 lib 层的rate limiterlib/ratelimit.h、lib/ratelimit.c实现。该模块注释开宗明义地指出其算法本质This is a rate limiter that provides tokens to be consumed per second. In the literature, this is referred to as a token bucket令牌桶.令牌桶模型以每秒 1 MiB为例lib/ratelimit.h 的注释描述了直观行为初始状态下桶里有 100 万令牌对应 1 MiB传输时令牌被逐字节抽取drain第一个秒内抽完若在下一秒到来之前检查可用令牌返回 0到达/超过下一秒后桶里重新补满 100 万令牌若中途空闲了一秒令牌会累积到 200 万但burst突发上限会把它封顶例如封顶在 150 万从而保证平均速率而非瞬时吞吐峰值被约束。核心数据结构struct Curl_rlimitlib/ratelimit.h包含struct Curl_rlimit { int64_t rate_per_sec; /* rate tokens generated per second */ int64_t burst_per_sec; /* burst rate of tokens per second */ int64_t rate_per_step; /* rate tokens generated per step us */ int64_t burst_per_step; /* burst rate of tokens per step us */ timediff_t step_us; /* microseconds between token increases */ int64_t tokens; /* tokens available in the next second */ timediff_t spare_us; /* microseconds unaffecting tokens */ struct curltime ts; /* time of the last update */ BIT(blocked); /* blocking sets available tokens to 0 */ };注释中还解释了 burst 语义的两极若把 burst 设为CURL_OFF_T_MAX趋近无穷大令牌在整个传输生命周期内持续累积则从开始到结束的平均速率约等于设定值对应文档所说 averaging ... over a period of multiple seconds若把 burst 设为与 rate 相同则传输会始终尝试保持不高于该速率空闲产生的多余令牌不会带来突发。引擎的关键函数lib/ratelimit.c 提供了整套原语Curl_rlimit_init()L154按每秒速率与突发速率初始化令牌桶初始即注入一个 step 的令牌Curl_rlimit_start()L171重置令牌桶并调用rlimit_tune_steps()依据本次传输预计消耗的总令牌数微调 step 时长——其注释L82-L152解释了为什么要调步默认按 1 秒为一步发放令牌若剩余流量不足一步例如以 1k 限速下载 1.5kb最后一跳可能瞬间跑完导致平均超速调步逻辑会把最后一步压缩到只分配总令牌的 1%至少 1 个使末尾不会出现超速冲刺Curl_rlimit_avail()L200返回当前可用令牌数blocked状态下恒为 0Curl_rlimit_drain()L219消耗令牌Curl_rlimit_wait_ms()L247计算还需等待多少毫秒令牌才会重新为正供调度层休眠Curl_rlimit_next_step_ms()L274返回距离下一次令牌补充还有多久Curl_rlimit_block()L289阻塞/解除阻塞限速解除后历史清零、从零重新开始计时。其中几个常量值得留意CURL_RLIMIT_MIN_RATE 4 * 1024调步后单步最少令牌数、CURL_RLIMIT_STEP_MIN_MS 2最小 step 时长过小的 step 会被放弃调步以及每步默认step_us CURL_US_PER_SEClib/ratelimit.c。与传输主循环的挂钩限速器被挂接在传输主循环的多个节点上从代码结构看形成了检查令牌 → 等待 → 读取/写入 → 抽取令牌的闭环初始化在 lib/setopt.c 中设置CURLOPT_MAX_SEND_SPEED_LARGE/CURLOPT_MAX_RECV_SPEED_LARGE时会分别对上传ul与下载dl两个方向调用Curl_rlimit_init启动每个传输方向开始时调用Curl_rlimit_startlib/sendf.c 与 lib/sendf.c抽取令牌实际收发字节后调用Curl_rlimit_drain例如 lib/progress.c 在进度统计更新时把本周期传输的字节数delta从对应令牌桶中扣除调度等待lib/multi.c 会先检测Curl_rlimit_avail()判断收发是否被限速阻塞随后在 lib/multi.c 用Curl_rlimit_wait_ms()/Curl_rlimit_next_step_ms()计算需要等待的毫秒数并据此延后相关事件暂停/恢复传输暂停时会Curl_rlimit_blocklib/transfer.c恢复时在 lib/request.c 解除阻塞并按当前时间重置阻塞期间不产生令牌。对 HTTP/2、HTTP/3 的适配限速令牌还被用于高级协议层面的流量控制例如 HTTP/2 的窗口与流控制需要感知可用令牌lib/http2.cHTTP/3QUIC/ngtcp2的cf-ngtcp2.c与代理链cf-ngtcp2-proxy.c也会查询Curl_rlimit_avail(data-progress.dl.rlimit)lib/vquic/cf-ngtcp2.c、lib/vquic/cf-ngtcp2-proxy.c。这意味着即便在 h2/h3 多路复用场景下--limit-rate依然能作用于聚合后的整体速率。限速的平均语义与窗口特性文档特别澄清了限速逻辑的工作方式The rate limiting logic works on averaging the transfer speed to no more than the set threshold over a period of multiple seconds.即 curl 并不保证任意一个瞬间都不超过阈值而是保证在一段以秒为单位的时间窗内平均速率不越过设定值。对应到令牌桶实现就是令牌按秒级 step 发放、burst 上限对闲时积攒进行封顶见 lib/ratelimit.h 的 burst 说明。因此对于很小的文件、很短的传输瞬时速率可能看起来超标传输时间越长整体平均速率越贴近设定值不要指望它对单个字节包做硬性节流。与--speed-limit、--speed-time的优先级关系--speed-limit与--speed-time是一对低速中止参数参见 speed-limit.md 与 speed-time.md如果传输速度持续低于--speed-limit指定的字节/秒并超过--speed-time指定的秒数默认 30 秒传输会被直接中止。这与--limit-rate仅限速、不中止目的相反。当两者同时使用时文档明确指出其优先级关系If you also use the --speed-limit option, that option takes precedence and might cripple the rate-limiting slightly, to help keep the speed-limit logic working.即--speed-limit优先。为了让低速检测能够正常触发否则传输始终以限速阈值附近的低速运行可能永远不会低于speed-limit而被认为仍在健康传输curl 会略微削弱限速——让实际节流稍稍放松一点、速度偶尔超过--limit-rate阈值从而保证--speed-limit的低速判定逻辑依然有效。这是两者共存时的有意为之而非 bug。因此实际组合策略通常是想要控制带宽占用→ 只用--limit-rate想要在链路异常变慢时及时退出→ 使用--speed-limit--speed-time想要限速 兜底→ 三者或与--max-time联用例如原文档示例curl --limit-rate 200K --max-time 60 $URL。通过 libcurl API 使用限速--limit-rate在命令行同时设置了两个 libcurl 选项见 src/config2setopts.c因此 libcurl 使用者可以分别对两个方向独立限速CURLOPT_MAX_RECV_SPEED_LARGE——限制下载速率字节/秒CURLOPT_MAX_SEND_SPEED_LARGE——限制上传速率字节/秒。这与命令行的一次设置、双向生效不同命令行因为只有一个参数值只能把同一个值赋给两个方向src/tool_getparam.c而通过 API 可以做到下载限 2M、上传限 500K这类不对称限速。例如CURL *curl curl_easy_init(); /* 下载不超过 2 MiB/s上传不超过 512 KiB/s */ curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)(2 * 1024 * 1024)); curl_easy_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t)(512 * 1024));与限速相关的还有CURLOPT_LOW_SPEED_LIMIT/CURLOPT_LOW_SPEED_TIME对应命令行--speed-limit/--speed-time可做低速中止。使用注意事项小结单位均为1024 进制1K 1024字节不是 1000后缀 k/m/g/t/p 大小写皆可解析时统一做小写匹配。从 8.19.0 起支持小数如2.5M但分隔符只能是英文句点.与 locale 无关小数解析超过单位精度时会被截断对齐见GetSizeParameter的修剪逻辑。速率默认同时作用于下载与上传若需非对称限速请直接使用 libcurl 的CURLOPT_MAX_RECV_SPEED_LARGE/CURLOPT_MAX_SEND_SPEED_LARGE。限速是秒级平均约束而非逐字节精确节流令牌桶的 burst 上限决定了它如何平滑闲时积攒带来的突发。与--speed-limit并存时后者优先限速会被轻微放松以维持低速检测的有效性limit-rate.md 原文说明。--limit-rate的 Category 为 connection、Multi 为 single同一命令行中重复出现时以最后一次为准--raterate.md则是另一个完全不同用途的选项——它限制的是发起请求的频率每秒/每分/每小时执行多少次传输实现于 src/tool_getparam.c 的set_rate勿与传输速率混淆。延伸阅读若需深入了解本文涉及的相邻主题可继续阅读仓库中的以下文档与源码选项主文档limit-rate.md相邻选项speed-limit.md、speed-time.md、rate.md令牌桶实现lib/ratelimit.c、lib/ratelimit.h参数解析与选项映射src/tool_getparam.c、src/config2setopts.c调度与字节抽取lib/multi.c、lib/progress.c、lib/transfer.c、lib/sendf.c【免费下载链接】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),仅供参考