强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

curl 深度教程 / 第 09 章:传输选项与网络调优

第 09 章:传输选项与网络调优

在生产环境中,网络状况千变万化。正确配置超时、重试和代理选项,是构建可靠网络应用的关键。


9.1 超时设置

超时参数对比

选项说明默认值推荐值
--connect-timeoutTCP 连接建立超时无限制10-30 秒
-m / --max-time整个操作最大耗时无限制60-300 秒
--max-filesize最大下载文件大小无限制视场景而定
--speed-limit + --speed-time速率低于阈值时中止视场景而定

基本超时配置

# 连接超时:10 秒内未建立连接则中止
curl --connect-timeout 10 https://slow-server.example.com

# 总超时:整个操作(含 DNS、连接、传输)最多 60 秒
curl --max-time 60 https://example.com/largefile.zip

# 组合使用
curl --connect-timeout 10 --max-time 300 \
  https://example.com/largefile.zip

# 最大文件大小(超过则中止)
curl --max-filesize 104857600 https://example.com/download
# 限制为 100MB

速率感知超时

# 如果 30 秒内平均速度低于 1KB/s,则中止
curl --speed-limit 1024 --speed-time 30 \
  -O https://example.com/slow-download.zip

# 用于检测服务器是否"卡住"
curl --speed-limit 100 --speed-time 60 \
  --max-time 300 \
  -O https://example.com/file.zip

超时场景参考

场景connect-timeoutmax-time说明
API 调用5-10 秒30 秒快速失败
网页下载10 秒60 秒允许加载时间
大文件下载30 秒3600+ 秒按文件大小调整
健康检查3 秒5 秒快速检测
批量请求5 秒30 秒单个请求级超时
慢速服务器30 秒600 秒容忍网络延迟

9.2 重试策略

基本重试

# 最多重试 3 次
curl --retry 3 -O https://example.com/unstable-server/file.zip

# 重试间隔 5 秒
curl --retry 3 --retry-delay 5 -O https://example.com/file.zip

# 使用指数退避(每次重试间隔翻倍)
curl --retry 3 --retry-delay 2 --retry-max-time 60 \
  -O https://example.com/file.zip
# 第 1 次重试:2 秒后
# 第 2 次重试:4 秒后
# 第 3 次重试:8 秒后

# 设置重试的最大总时间
curl --retry 10 --retry-max-time 120 \
  -O https://example.com/file.zip
# 重试总时间不超过 2 分钟

重试触发条件

curl 默认在以下 HTTP 状态码时重试:

状态码含义默认重试
408Request Timeout
429Too Many Requests
500Internal Server Error
502Bad Gateway
503Service Unavailable
504Gateway Timeout
# 自定义重试条件(curl 7.66+)
curl --retry 3 \
  --retry-connrefused \
  --retry-all-errors \
  -O https://example.com/file.zip

# --retry-connrefused:连接被拒绝时也重试
# --retry-all-errors:所有错误都重试(包括 HTTP 错误)

生产级重试脚本

#!/bin/bash
# resilient_download.sh - 可靠的下载脚本

URL="$1"
OUTPUT="$2"
MAX_RETRIES=${3:-5}
RETRY_DELAY=${4:-5}
MAX_RETRY_TIME=${60:-300}

download() {
  curl -sS -o "$OUTPUT" \
    --connect-timeout 10 \
    --max-time 600 \
    --retry "$MAX_RETRIES" \
    --retry-delay "$RETRY_DELAY" \
    --retry-max-time "$MAX_RETRY_TIME" \
    --retry-connrefused \
    --retry-all-errors \
    --speed-limit 10240 \
    --speed-time 60 \
    -C - \
    "$URL"
}

if download; then
  FILE_SIZE=$(stat -c%s "$OUTPUT" 2>/dev/null || echo 0)
  echo "✅ 下载成功: $OUTPUT ($FILE_SIZE bytes)"
else
  echo "❌ 下载失败: $URL"
  rm -f "$OUTPUT"
  exit 1
fi

9.3 代理配置

HTTP 代理

# 使用 HTTP 代理
curl -x http://proxy.example.com:8080 https://example.com

# 使用 HTTPS 代理
curl -x https://proxy.example.com:8443 https://example.com

# 需要认证的代理
curl -x http://proxy.example.com:8080 \
  -U proxyuser:proxypass \
  https://example.com

# 或在 URL 中包含认证信息
curl -x http://proxyuser:[email protected]:8080 \
  https://example.com

# 使用环境变量设置代理
export http_proxy=http://proxy.example.com:8080
export https_proxy=http://proxy.example.com:8080
export no_proxy=localhost,127.0.0.1,.internal.example.com

curl https://external.example.com  # 通过代理
curl https://internal.example.com  # 不通过代理(匹配 no_proxy)

SOCKS 代理

# SOCKS4 代理
curl --socks4 127.0.0.1:1080 https://example.com

# SOCKS4a 代理(支持远程 DNS)
curl --socks4a 127.0.0.1:1080 https://example.com

# SOCKS5 代理
curl --socks5 127.0.0.1:1080 https://example.com

# SOCKS5 + 远程 DNS 解析(推荐)
curl --socks5-hostname 127.0.0.1:1080 https://example.com

# SOCKS5 代理认证
curl --socks5 127.0.0.1:1080 \
  --proxy-user proxyuser:proxypass \
  https://example.com

# 环境变量
export ALL_PROXY=socks5://127.0.0.1:1080
curl https://example.com

代理类型对比

类型选项特点适用场景
HTTP 代理-x http://仅代理 HTTP 流量Web 访问
HTTPS 代理-x https://TLS 隧道到代理安全环境
CONNECT 代理-p / --proxytunnel隧道模式HTTPS 流量
SOCKS4--socks4TCP 代理,不支持远程 DNS旧应用
SOCKS4a--socks4a支持远程 DNS需要 DNS 隐私
SOCKS5--socks5支持 TCP/UDP通用代理
SOCKS5h--socks5-hostname远程 DNS 解析推荐

代理排除规则

# 使用 --noproxy 排除特定主机
curl --noproxy "localhost,127.0.0.1,.internal.com" \
  -x http://proxy.example.com:8080 \
  https://api.internal.com/data
# 不使用代理

# 使用环境变量(更通用)
export no_proxy="localhost,127.0.0.1,.internal.example.com,10.0.0.0/8"

9.4 连接管理

连接池与 Keep-Alive

# curl 默认使用 HTTP/1.1 Keep-Alive
# 同一连接会自动复用

# 在同一连接上发送多个请求(使用 --next)
curl https://api.example.com/users \
  --next https://api.example.com/orders \
  --next https://api.example.com/products

# 强制关闭连接(禁用 Keep-Alive)
curl -H "Connection: close" https://api.example.com/data

DNS 缓存

# curl 默认不缓存 DNS(每次请求都解析)
# 使用 --resolve 手动指定 DNS 解析
curl --resolve example.com:443:93.184.216.34 https://example.com

# 使用 c-ares 进行异步 DNS(编译时启用 --enable-ares)
# 这样 curl 会缓存 DNS 结果

# 指定 DNS 服务器
curl --dns-servers 8.8.8.8,8.8.4.4 https://example.com
# 需要 c-ares 支持

# DNS 解析超时
curl --dns-timeout 10 https://example.com

IPv4/IPv6 控制

# 强制使用 IPv4
curl -4 https://example.com

# 强制使用 IPv6
curl -6 https://example.com

# 查看实际使用的 IP 版本
curl -v -4 https://example.com 2>&1 | grep "Connected"
# Connected to example.com (93.184.216.34) port 443

curl -v -6 https://example.com 2>&1 | grep "Connected"
# Connected to example.com (2606:2800:220:1:...) port 443

9.5 网络接口绑定

# 绑定到特定网络接口
curl --interface eth0 https://example.com

# 绑定到特定 IP 地址
curl --interface 192.168.1.100 https://example.com

# 指定本地端口范围
curl --local-port 5000-6000 https://example.com

# 多网卡环境下的出站控制
curl --interface 10.0.1.5 https://internal.example.com
curl --interface 192.168.1.5 https://external.example.com

9.6 TCP 参数调优

# 设置 TCP 连接的 keep-alive 间隔
curl --keepalive-time 60 https://example.com

# 禁用 TCP 缓冲(减少延迟,降低吞吐)
curl --tcp-nodelay https://example.com

# 设置最大连接数(配合 --next)
# 单个 curl 实例的连接数由请求数决定

# 使用 HTTP/1.0(禁用 keep-alive)
curl --http1.0 https://example.com

9.7 速率限制与带宽管理

# 限制上传速度
curl --limit-rate 1m -X PUT \
  -F "[email protected]" \
  https://upload.example.com

# 组合限速 + 断点续传
curl --limit-rate 2m -C - -O https://example.com/largefile.iso

# 限制请求速率(脚本中实现)
while read -r url; do
  curl -sO "$url"
  sleep 0.5  # 每个请求间隔 500ms
done < urls.txt

# 使用令牌桶算法(GNU parallel)
cat urls.txt | parallel -j 1 --delay 0.5 curl -sO {}

注意事项

  1. 代理环境变量优先级curl -x > https_proxy > http_proxy
  2. SOCKS5h 推荐:使用 --socks5-hostname 避免 DNS 泄露
  3. 超时层级--connect-timeout < --max-time < --retry-max-time
  4. 重试间隔:避免过于频繁的重试导致服务器过载(使用指数退避)
  5. 连接复用:同一目标的多个请求自动复用 TCP 连接
# 完整的网络诊断命令
curl -v --connect-timeout 5 --max-time 30 \
  -4 --interface eth0 \
  -x "" \  # 忽略代理环境变量
  https://example.com 2>&1 | head -30

扩展阅读


📖 下一章第 10 章:TLS/SSL 安全 — 深入了解 TLS 配置、证书验证、自签名证书和密码套件管理。