curl 分析 请求时长

使用curl分析HTTP请求耗时

转载链接: https://cizixs.com/2017/04/11/use-curl-to-analyze-request/

最近工作中遇到一个问题,某个请求的响应特别慢,因此我就希望有一种方法能够分析到底请求的哪一步耗时比较长,好进一步找到问题的原因。在网络上搜索了一下,发现了一个非常好用的方法,curl 命令就能帮你分析请求的各个部分耗时。

curl 命令提供了 -w 参数,这个参数在 manpage 是这样解释的:

 -w, --write-out <format>
              Make curl display information on stdout after a completed transfer. The format is a string that may contain plain text mixed with any number of variables. The  format
              can  be  specified  as  a literal "string", or you can have curl read the format from a file with "@filename" and to tell curl to read the format from stdin you write
              "@-".

              The variables present in the output format will be substituted by the value or text that curl thinks fit, as described below. All variables are specified  as  %{vari‐
              able_name} and to output a normal % you just write them as %%. You can output a newline by using \n, a carriage return with \r and a tab space with \t.

它能够按照指定的格式打印某些信息,里面可以使用某些特定的变量,而且支持 \n\t和 \r转义字符。提供的变量很多,比如 status_codelocal_portsize_download 等等,这篇文章我们只关注和请求时间有关的变量(以 time_ 开头的变量)。

先往文本文件 curl-format.txt 写入下面的内容:

➜  ~ cat curl-format.txt
    time_namelookup:  %{time_namelookup}\n
       time_connect:  %{time_connect}\n
    time_appconnect:  %{time_appconnect}\n
      time_redirect:  %{time_redirect}\n
   time_pretransfer:  %{time_pretransfer}\n
 time_starttransfer:  %{time_starttransfer}\n
                    ----------\n
         time_total:  %{time_total}\n

那么这些变量都是什么意思呢?我解释一下:

  • time_namelookup:DNS 域名解析的时候,就是把 https://zhihu.com 转换成 ip 地址的过程
  • time_connect:TCP 连接建立的时间,就是三次握手的时间
  • time_appconnect:SSL/SSH 等上层协议建立连接的时间,比如 connect/handshake 的时间
  • time_redirect:从开始到最后一个请求事务的时间
  • time_pretransfer:从请求开始到响应开始传输的时间
  • time_starttransfer:从请求开始到第一个字节将要传输的时间
  • time_total:这次请求花费的全部时间

我们先看看一个简单的请求,没有重定向,也没有 SSL 协议的时间:

➜  ~ curl -w "@curl-format.txt" -o /dev/null -s -L "http://cizixs.com"
    time_namelookup:  0.012
       time_connect:  0.227
    time_appconnect:  0.000
      time_redirect:  0.000
   time_pretransfer:  0.227
 time_starttransfer:  0.443
                    ----------
         time_total:  0.867

可以看到这次请求各个步骤的时间都打印出来了,每个数字的单位都是秒(seconds),这样可以分析哪一步比较耗时,方便定位问题。这个命令各个参数的意义:

  • -w:从文件中读取要打印信息的格式
  • -o /dev/null:把响应的内容丢弃,因为我们这里并不关心它,只关心请求的耗时情况
  • -s:不要打印进度条

从这个输出,我们可以算出各个步骤的时间:

  • DNS 查询:12ms
  • TCP 连接时间:pretransfter(227) - namelookup(12) = 215ms
  • 服务器处理时间:starttransfter(443) - pretransfer(227) = 216ms
  • 内容传输时间:total(867) - starttransfer(443) = 424ms

来个比较复杂的,访问某度首页,带有中间有重定向和 SSL 协议:

➜  ~ curl -w "@curl-format.txt" -o /dev/null -s -L "https://baidu.com"
    time_namelookup:  0.012
       time_connect:  0.018
    time_appconnect:  0.328
      time_redirect:  0.356
   time_pretransfer:  0.018
 time_starttransfer:  0.027
                    ----------
         time_total:  0.384

可以看到 time_appconnect 和 time_redirect 都不是 0 了,其中 SSL 协议处理时间为 328-18=310ms。而且 pretransfer 和 starttransfer 的时间都缩短了,这是重定向之后请求的时间。

参考资料

 

<think>我们正在讨论如何使用curl来显示请求耗费的时间。根据引用[1]和引用[2],curl提供了一个`-w`(或`--write-out`)选项,可以输出请求各个阶段的耗时情况。我们可以通过这个选项来获取详细的耗时信息。 引用[1]中列举了各个时间阶段的含义: - `time_namelookup`:从请求开始到域名解析完成的耗时 - `time_connect`:从请求开始到TCP三次握手完成耗时 - `time_appconnect`:从请求开始到SSL/TLS握手完成的耗时(如果使用了HTTPS) - `time_pretransfer`:从请求开始到向服务器发送第一个请求开始之前的耗时 - `time_redirect`:重定向时间(如果有重定向) - `time_starttransfer`:从请求开始到即将接收第一个字节前的时间 - `time_total`:总耗时 引用[2]也提到了类似的时间变量,并给出了一个实例。 因此,我们可以使用`-w`参数并指定一个格式字符串,其中包含我们想要的时间变量。同时,为了不干扰输出内容,我们可以将输出重定向到/dev/null(如果我们只关心时间信息)。 基本命令格式: ```bash curl -w "格式字符串" -o /dev/null -s "URL" ``` 其中: `-w`:指定输出格式 `-o /dev/null`:将输出的内容重定向到空设备,即不显示内容 `-s`:安静模式,不显示进度和错误信息 我们可以构建一个格式字符串,例如: "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_redirect: %{time_redirect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" 但是,为了更简洁,我们也可以将其写在一行,或者按照自己的需求选择部分变量。 另外,引用[3]和引用[4]与本次问题不太相关,我们主要关注引用[1]和引用[2]。 示例命令: ```bash curl -w "dnslookup: %{time_namelookup}s | connect: %{time_connect}s | appconnect: %{time_appconnect}s | pretransfer: %{time_pretransfer}s | starttransfer: %{time_starttransfer}s | total: %{time_total}s\n" -o /dev/null -s https://example.com ``` 注意:上面的变量后面用`s`表示单位是秒,但实际上curl输出的时间单位是秒(可能是小数)。也可以使用其他的格式。 另外,为了方便,我们可以将格式字符串写在一个文件中,然后通过`-w @filename`来引用。 例如,创建一个文件`format.txt`,内容为: ``` time_namelookup: %{time_namelookup}\n time_connect: %{time_connect}\n time_appconnect: %{time_appconnect}\n time_redirect: %{time_redirect}\n time_pretransfer: %{time_pretransfer}\n time_starttransfer: %{time_starttransfer}\n ----------\n time_total: %{time_total}\n ``` 然后使用: ```bash curl -w "@format.txt" -o /dev/null -s "https://example.com" ``` 这样输出会更整齐。 此外,我们也可以使用预定义的格式,比如只输出总时间: ```bash curl -w "%{time_total}" -o /dev/null -s https://example.com ``` 这样只会输出一个数字(单位:秒),便于脚本处理。 总结步骤: 1. 确定需要查看的时间变量(根据引用[1]的释义)。 2. 使用`-w`参数指定这些变量,并按照需要的格式输出。 3. 使用`-o /dev/null`和`-s`来隐藏其他输出。 注意:如果请求发生了重定向,那么这些时间变量会包括重定向过程中的时间。另外,`time_total`是总时间,包括所有阶段。 下面是一个实际的例子(以百度为例): ```bash curl -w "dnslookup: %{time_namelookup}\nconnect: %{time_connect}\nappconnect: %{time_appconnect}\npretransfer: %{time_pretransfer}\nstarttransfer: %{time_starttransfer}\ntotal: %{time_total}\n" -o /dev/null -s "https://www.baidu.com" ``` 输出结果可能类似于: ``` dnslookup: 0.004 connect: 0.007 appconnect: 0.032 pretransfer: 0.032 starttransfer: 0.053 total: 0.053 ``` 注意:在HTTPS请求中,`time_appconnect`(SSL握手时间)通常是一个重要的部分。 另外,引用[2]中提到了变量`http_code`,我们也可以加入这个变量来获取HTTP状态码。 例如: ```bash curl -w "http_code: %{http_code}\ntime_total: %{time_total}\n" -o /dev/null -s "https://example.com" ``` 这样就可以同时得到状态码和总时间。 因此,根据用户的需求(显示请求耗费时间),我们可以通过上述方法实现。 </think>好的,我将详细介绍如何使用 curl 显示请求各阶段耗时时间,并提供实用的命令示例。 ### 📊 curl 显示请求耗时的方法 curl 使用 `-w` (write-out) 参数配合特定变量获取耗时信息,结合 `-o /dev/null` 和 `-s` 参数可得到清晰的时间分析: ```bash curl -w " DNS解析: %{time_namelookup}s TCP连接: %{time_connect}s TLS握手: %{time_appconnect}s 请求准备: %{time_pretransfer}s 首字节响应: %{time_starttransfer}s 总耗时: %{time_total}s " \ -o /dev/null -s "https://example.com" ``` ### 📝 输出结果示例: ``` DNS解析: 0.003s TCP连接: 0.021s TLS握手: 0.045s 请求准备: 0.045s 首字节响应: 0.125s 总耗时: 0.145s ``` ### 🔍 各阶段详解(单位:秒): 1. **`time_namelookup`** 域名解析耗时(DNS查询时间) 2. **`time_connect`** TCP连接建立耗时(包含DNS时间)[^1] 3. **`time_appconnect`** SSL/TLS握手完成耗时(仅HTTPS)[^1] 4. **`time_pretransfer`** 请求准备完成时间(包含所有预传输操作)[^1] 5. **`time_starttransfer`** 首字节响应时间(服务器处理时间 + 网络延迟)[^1] 6. **`time_total`** 请求总耗时(从开始到连接关闭)[^2] ### 🛠️ 实用技巧: 1. **简化输出格式**(适用于脚本处理): ```bash curl -w "%{time_total}" -o /dev/null -s https://api.example.com ``` 2. **保存格式化模板到文件**(`time-format.txt`): ```txt \nDNS: %{time_namelookup} TCP: %{time_connect} SSL: %{time_appconnect}\n响应: %{time_starttransfer} 总计: %{time_total}\n ``` 调用方式: ```bash curl -w "@time-format.txt" -so /dev/null https://example.com ``` 3. **结合超时参数**: ```bash curl -w "总耗时: %{time_total}s" --connect-timeout 3 --max-time 10 -s https://example.com ``` ### 📌 注意事项: - 使用 `-o /dev/null` 丢弃响应体,确保只输出时间信息 - 添加 `-s` (silent) 参数隐藏进度条 - HTTPS 请求会显示 `time_appconnect`,HTTP 请求该值为 0 - 重定向请求会自动包含 `time_redirect` 值[^2] --- ❓**相关问题** 1. 如何区分网络延迟和服务器处理时间? 2. 当 DNS 解析时间过长时应如何排查? 3. 为什么 `time_connect` 总是大于 `time_namelookup`? 4. HTTPS 请求中 TLS 握手时间异常的常见原因有哪些?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值