HTTPS 请求慢,怎样用 curl 区分连接与首字节耗时?
HTTPS 请求慢时,可用 curl 的 write-out 同时记录解析、连接、TLS 握手、首字节和总耗时。这些值多为从请求开始计算的累计时间,先比较阶段差值,再结合代理、响应状态和服务端日志判断,不能把首字节时间直接当成后端执行时间。
适用版本与前提
本文面向 Linux shell 中支持 HTTPS 的 curl 7.58.0 及以上版本,依据发布时查阅的 curl 官方手册整理,未在目标网络实测。先运行 curl --version 记录版本和 TLS 后端。示例域名需要替换为自己管理或获授权的目标,选择可安全 GET 的路径,并记录来源网络、代理与故障时间。
第一步,采集一次完整请求的时间点
curl --version
curl --silent --show-error --connect-timeout 5 --max-time 30 \
--output /dev/null \
--write-out 'http=%{http_code} remote=%{remote_ip} dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ready=%{time_pretransfer} first=%{time_starttransfer} total=%{time_total}\n' https://www.example.com/
rc=$?
printf 'curl_exit=%s\n' "$rc"--silent 与 --show-error 隐藏进度并保留错误。--output /dev/null 丢弃响应体,仍会下载响应内容。--write-out 在传输结束后输出指定字段,rc 必须紧接 curl 保存。格式变量与换行语法见 官方 write-out 用法。
本例每次启动新的 curl 进程,只访问一个 URL,不自动跟随重定向。收到 3xx 时应记录当前结果,确认跳转目标及访问权限后再单独测试。5 秒连接限时和 30 秒总限时都是示例值,应根据业务预期调整。
第二步,区分累计时间和阶段时间
time_namelookup 是解析结束时刻,time_connect 是 TCP 连接完成时刻,time_appconnect 是 TLS 等握手完成时刻,均从传输开始计时。time_pretransfer 表示准备传输前的时间,time_starttransfer 表示收到首字节前的时间,time_total 是完整操作总时间,单位为秒。字段定义见 curl 官方时间变量说明。
对于本例这种单 URL、无重定向、直连且新建连接的普通 HTTPS 请求,可把 connect 减 dns、tls 减 connect 作为 TCP 与 TLS 阶段的近似线索。first 减 ready 包含请求发送、网络往返及服务端等待,不能直接等同应用执行耗时。total 减 first 可辅助观察首字节之后的传输阶段。
这些差值是限定场景下的诊断推断。使用代理、复用连接、不同 HTTP 协议或请求中途失败时,应回到完整连接上下文解读。字段为零或尚未完成不能解释成某阶段性能完美。
第三步,用对照样本缩小范围
- 固定 URL、GET 方法、来源网络和 curl 参数,低频采样并分别保存每次状态、退出码、远端地址和耗时。
- 比较成功与异常样本,先检查是否访问了同一地址、相同响应状态以及相近响应内容规模。
- 若连接前阶段明显变长,结合解析和网络路径继续核查;若首字节之前增长,使用对应时间的代理及应用日志确认。
- 调整一个条件后重复相同采样,并用真实业务客户端验证受影响操作。
单次请求可能受临时负载、缓存、DNS 缓存或路径变化影响,不据此承诺优化效果。示例丢弃了正文,仍需另行核对实际业务内容。
常见问题与验证边界
超时之后还能把总耗时当作完整响应时间吗?
达到 --max-time 时传输会被中止,退出码为 28,记录只能描述被限制的那次尝试。--connect-timeout 包含解析及连接所需握手阶段;它不是纯 TCP 限时。参阅 curl 官方超时说明。
curl_exit 为零,是否代表业务正常?
本例没有设置 --fail,HTTP 4xx/5xx 仍可能伴随零退出码。应把传输结果与 HTTP 状态分开判断,错误分层可参考本站 curl 排查 DNS、连接、证书与 HTTP 状态。
若站点使用 Nginx 反向代理,可进一步对照 Nginx 上游请求耗时日志,用同一请求和时间定位服务端阶段。本文为资料整理,未提供亲测耗时或性能提升数据。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭