如何使用cURL同时测量请求和响应时间?

我有一个Web服务,它接收JSON格式的数据,处理数据,然后将结果返回给请求者。

我想使用cURL来测量请求、响应和总时间。

我的示例请求如下所示:

curl -X POST -d @file server:port

我目前使用Linux中的time命令来测量它:

time curl -X POST -d @file server:port

不过,time命令只测量共计时间——这不是我想要的。

有没有办法使用cURL来测量请求和响应时间?

691833 次浏览

以下是答案:

curl -X POST -d @file server:port -w %{time_connect}:%{time_starttransfer}:%{time_total}

-w中使用的所有变量都可以在man curl中找到。

从这篇精彩的博客文章…https://blog.josephscott.org/2011/10/14/timing-details-with-curl/

cURL支持请求细节的格式化输出(参见cURL手册页了解详细信息,在-w, –write-out <format>下)。出于我们的目的,我们将只关注提供的时间细节。下面的时间在中。

  1. 创建一个新文件#0,然后粘贴:

         time_namelookup:  %{time_namelookup}s\ntime_connect:  %{time_connect}s\ntime_appconnect:  %{time_appconnect}s\ntime_pretransfer:  %{time_pretransfer}s\ntime_redirect:  %{time_redirect}s\ntime_starttransfer:  %{time_starttransfer}s\n----------\ntime_total:  %{time_total}s\n
  2. 做一个请求:

     curl -w "@curl-format.txt" -o /dev/null -s "http://wordpress.com/"

    在Windows上,它是…

     curl -w "@curl-format.txt" -o NUL -s "http://wordpress.com/"

这是做什么的:

-w "@curl-format.txt"告诉cURL使用我们的格式文件
-o /dev/null将请求的输出重定向到 /dev/null
-s告诉cURL不要显示进度计
"http://wordpress.com/"是我们请求的URL。特别是如果您的URL具有“&”查询字符串参数,请使用引号


这是你得到的结果:

   time_namelookup:  0.001stime_connect:  0.037stime_appconnect:  0.000stime_pretransfer:  0.037stime_redirect:  0.000stime_starttransfer:  0.092s----------time_total:  0.164s

我还没有看到在微秒内输出结果的选项,但如果您知道一个,请在下面的评论中发布。


创建Linux /Mac快捷方式(别名)

alias curltime="curl -w \"@$HOME/.curl-format.txt\" -o /dev/null -s "

然后你可以简单地叫…

curltime wordpress.org

感谢评论者Pete Doyle!


制作Linux /Mac独立脚本

此脚本不需要单独的.txt文件来包含格式。

在您的可执行路径中的某个位置创建一个新文件curltime,然后粘贴:

#!/bin/bash
curl -w @- -o /dev/null -s "$@" <<'EOF'time_namelookup:  %{time_namelookup}\ntime_connect:  %{time_connect}\ntime_appconnect:  %{time_appconnect}\ntime_pretransfer:  %{time_pretransfer}\ntime_redirect:  %{time_redirect}\ntime_starttransfer:  %{time_starttransfer}\n----------\ntime_total:  %{time_total}\nEOF

然后以与别名相同的方式调用它:

curltime wordpress.org

创建Windows快捷方式(又名BAT文件)

在与curl.execurl-format.txt相同的文件夹中创建一个名为curltime.bat的新文本文件,并粘贴到以下行:

curl -w "@%~dp0curl-format.txt" -o NUL -s %*

然后从命令行您可以简单地调用:

curltime wordpress.org

(确保文件夹在WindowsPATH变量中列出,以便能够使用任何文件夹中的命令。)

备选案文1:测量total time

curl -o /dev/null -s -w 'Total: %{time_total}s\n'  https://www.google.com

示例输出:

Total: 0.441094s

备选案文2:得到time to establish connectiontime to first byte (TTFB)total time

curl -o /dev/null -s -w 'Establish Connection: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n'  https://www.google.com

示例输出:

Establish Connection: 0.020033sTTFB: 0.417907sTotal: 0.435486s

参考:使用curl获取响应时间

您可以根据此处的其他答案添加到. bashrc等中的快捷方式:

function perf {curl -o /dev/null -s -w "%{time_connect} + %{time_starttransfer} = %{time_total}\n" "$1"}

用法:

> perf stackoverflow.com0.521 + 0.686 = 1.290

我制作了一个友好的格式化程序来嗅探curl请求以帮助调试(请参阅使用注释)。它包含您可以以易于阅读的格式编写的所有已知输出参数。

https://gist.github.com/manifestinteractive/ce8dec10dcb4725b8513

如果你想分析或总结延迟,你可以尝试apache Bench:

ab -n [number of samples] [url]

例如:

ab -n 100 http://www.google.com/

它将显示:

This is ApacheBench, Version 2.3 <$Revision: 1757674 $>Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.google.com (be patient).....done

Server Software:        gwsServer Hostname:        www.google.comServer Port:            80
Document Path:          /Document Length:        12419 bytes
Concurrency Level:      1Time taken for tests:   10.700 secondsComplete requests:      100Failed requests:        97(Connect: 0, Receive: 0, Length: 97, Exceptions: 0)Total transferred:      1331107 bytesHTML transferred:       1268293 bytesRequests per second:    9.35 [#/sec] (mean)Time per request:       107.004 [ms] (mean)Time per request:       107.004 [ms] (mean, across all concurrent requests)Transfer rate:          121.48 [Kbytes/sec] received
Connection Times (ms)min  mean[+/-sd] median   maxConnect:       20   22   0.8     22      26Processing:    59   85 108.7     68     911Waiting:       59   85 108.7     67     910Total:         80  107 108.8     90     932
Percentage of the requests served within a certain time (ms)50%     9066%     9175%     9380%     9590%    10595%    11198%    77399%    932100%    932 (longest request)

Hey比Apache Bench更好,SSL问题更少

./hey https://google.com -moreSummary:Total:    3.0960 secsSlowest:  1.6052 secsFastest:  0.4063 secsAverage:  0.6773 secsRequests/sec: 64.5992
Response time histogram:0.406 [1] |0.526 [142]   |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎0.646 [1] |0.766 [6] |∎∎0.886 [0] |1.006 [0] |1.126 [0] |1.246 [12]    |∎∎∎1.365 [32]    |∎∎∎∎∎∎∎∎∎1.485 [5] |∎1.605 [1] |
Latency distribution:10% in 0.4265 secs25% in 0.4505 secs50% in 0.4838 secs75% in 1.2181 secs90% in 1.2869 secs95% in 1.3384 secs99% in 1.4085 secs
Details (average, fastest, slowest):DNS+dialup:    0.1150 secs, 0.0000 secs, 0.4849 secsDNS-lookup:    0.0032 secs, 0.0000 secs, 0.0319 secsreq write:     0.0001 secs, 0.0000 secs, 0.0007 secsresp wait:     0.2068 secs, 0.1690 secs, 0.4906 secsresp read:     0.0117 secs, 0.0011 secs, 0.2375 secs
Status code distribution:[200] 200 responses

参考文献

以下内容受到Simon答案的启发。它是自包含的(不需要单独的格式文件),这使得它非常适合包含在.bashrc中。

curl_time() {curl -so /dev/null -w "\namelookup:  %{time_namelookup}s\n\connect:  %{time_connect}s\n\appconnect:  %{time_appconnect}s\n\pretransfer:  %{time_pretransfer}s\n\redirect:  %{time_redirect}s\n\starttransfer:  %{time_starttransfer}s\n\-------------------------\n\total:  %{time_total}s\n" "$@"}

此外,它应该适用于curl通常接受的所有参数,因为"$@"只是传递它们。例如,您可以执行:

curl_time -X POST -H "Content-Type: application/json" -d '{"key": "val"}' https://postman-echo.com/post

输出:

   namelookup:  0,125000sconnect:  0,250000sappconnect:  0,609000spretransfer:  0,609000sredirect:  0,000000sstarttransfer:  0,719000s-------------------------total:  0,719000s

以下是重复访问同一服务器的Bash单行代码:

for i in {1..1000}; do curl -s -o /dev/null -w "%{time_total}\n" http://server/get_things; done

另一个可能是命令行方面的最简单选项是添加内置--trace-time选项:

curl -X POST -d @file server:port --trace-time

尽管从技术上讲,它没有按照OP的请求输出各个步骤的时间,但它确实显示了请求的所有步骤的时间戳,如下所示。使用它,您可以(相当容易地)计算每个步骤花费了多长时间。

$ curl https://www.google.com --trace-time -v -o /dev/null13:29:11.148734 * Rebuilt URL to: https://www.google.com/% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     013:29:11.149958 *   Trying 172.217.20.36...13:29:11.149993 * TCP_NODELAY set13:29:11.163177 * Connected to www.google.com (172.217.20.36) port 443 (#0)13:29:11.164768 * ALPN, offering h213:29:11.164804 * ALPN, offering http/1.113:29:11.164833 * successfully set certificate verify locations:13:29:11.164863 *   CAfile: noneCApath: /etc/ssl/certs13:29:11.165046 } [5 bytes data]13:29:11.165099 * (304) (OUT), TLS handshake, Client hello (1):13:29:11.165128 } [512 bytes data]13:29:11.189518 * (304) (IN), TLS handshake, Server hello (2):13:29:11.189537 { [100 bytes data]13:29:11.189628 * TLSv1.2 (IN), TLS handshake, Certificate (11):13:29:11.189658 { [2104 bytes data]13:29:11.190243 * TLSv1.2 (IN), TLS handshake, Server key exchange (12):13:29:11.190277 { [115 bytes data]13:29:11.190507 * TLSv1.2 (IN), TLS handshake, Server finished (14):13:29:11.190539 { [4 bytes data]13:29:11.190770 * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):13:29:11.190797 } [37 bytes data]13:29:11.190890 * TLSv1.2 (OUT), TLS change cipher, Client hello (1):13:29:11.190915 } [1 bytes data]13:29:11.191023 * TLSv1.2 (OUT), TLS handshake, Finished (20):13:29:11.191053 } [16 bytes data]13:29:11.204324 * TLSv1.2 (IN), TLS handshake, Finished (20):13:29:11.204358 { [16 bytes data]13:29:11.204417 * SSL connection using TLSv1.2 / ECDHE-ECDSA-CHACHA20-POLY130513:29:11.204451 * ALPN, server accepted to use h213:29:11.204483 * Server certificate:13:29:11.204520 *  subject: C=US; ST=California; L=Mountain View; O=Google LLC; CN=www.google.com13:29:11.204555 *  start date: Oct  2 07:29:00 2018 GMT13:29:11.204585 *  expire date: Dec 25 07:29:00 2018 GMT13:29:11.204623 *  subjectAltName: host "www.google.com" matched cert's "www.google.com"13:29:11.204663 *  issuer: C=US; O=Google Trust Services; CN=Google Internet Authority G313:29:11.204701 *  SSL certificate verify ok.13:29:11.204754 * Using HTTP2, server supports multi-use13:29:11.204795 * Connection state changed (HTTP/2 confirmed)13:29:11.204840 * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=013:29:11.204881 } [5 bytes data]13:29:11.204983 * Using Stream ID: 1 (easy handle 0x55846ef24520)13:29:11.205034 } [5 bytes data]13:29:11.205104 > GET / HTTP/213:29:11.205104 > Host: www.google.com13:29:11.205104 > User-Agent: curl/7.61.013:29:11.205104 > Accept: */*13:29:11.205104 >13:29:11.218116 { [5 bytes data]13:29:11.218173 * Connection state changed (MAX_CONCURRENT_STREAMS == 100)!13:29:11.218211 } [5 bytes data]13:29:11.251936 < HTTP/2 20013:29:11.251962 < date: Fri, 19 Oct 2018 10:29:11 GMT13:29:11.251998 < expires: -113:29:11.252046 < cache-control: private, max-age=013:29:11.252085 < content-type: text/html; charset=ISO-8859-113:29:11.252119 < p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."13:29:11.252160 < server: gws13:29:11.252198 < x-xss-protection: 1; mode=block13:29:11.252228 < x-frame-options: SAMEORIGIN13:29:11.252262 < set-cookie: 1P_JAR=2018-10-19-10; expires=Sun, 18-Nov-2018 10:29:11 GMT; path=/; domain=.google.com13:29:11.252297 < set-cookie: NID=141=pzXxp1jrJmLwFVl9bLMPFdGCtG8ySQKxB2rlDWgerrKJeXxfdmB1HhJ1UXzX-OaFQcnR1A9LKYxi__PWMigjMBQHmI3xkU53LI_TsYRbkMNJNdxs-caQQ7fEcDGE694S; expires=Sat, 20-Apr-2019 10:29:11 GMT; path=/; domain=.google.com; HttpOnly13:29:11.252336 < alt-svc: quic=":443"; ma=2592000; v="44,43,39,35"13:29:11.252368 < accept-ranges: none13:29:11.252408 < vary: Accept-Encoding13:29:11.252438 <13:29:11.252473 { [5 bytes data]100 12215    0 12215    0     0   112k      0 --:--:-- --:--:-- --:--:--  112k13:29:11.255674 * Connection #0 to host www.google.com left intact

另一种方法是像这样配置~/.curlrc

-w "\n\n==== cURL measurements stats ====\ntotal: %{time_total} seconds \nsize: %{size_download} bytes \ndnslookup: %{time_namelookup} seconds \nconnect: %{time_connect} seconds \nappconnect: %{time_appconnect} seconds \nredirect: %{time_redirect} seconds \npretransfer: %{time_pretransfer} seconds \nstarttransfer: %{time_starttransfer} seconds \ndownloadspeed: %{speed_download} byte/sec \nuploadspeed: %{speed_upload} byte/sec \n\n"

所以curl的输出是

❯❯ curl -I https://google.comHTTP/2 301location: https://www.google.com/content-type: text/html; charset=UTF-8date: Mon, 04 Mar 2019 08:02:43 GMTexpires: Wed, 03 Apr 2019 08:02:43 GMTcache-control: public, max-age=2592000server: gwscontent-length: 220x-xss-protection: 1; mode=blockx-frame-options: SAMEORIGINalt-svc: quic=":443"; ma=2592000; v="44,43,39"


==== cURL measurements stats ====total: 0.211117 secondssize: 0 bytesdnslookup: 0.067179 secondsconnect: 0.098817 secondsappconnect: 0.176232 secondsredirect: 0.000000 secondspretransfer: 0.176438 secondsstarttransfer: 0.209634 secondsdownloadspeed: 0.000 byte/secuploadspeed: 0.000 byte/sec

这是您可以与-w一起使用的字符串,包含curl -w支持的所有选项。

{"contentType":"%{content_type}","filenameEffective":"%{filename_effective}","ftpEntryPath":"%{ftp_entry_path}","httpCode":"%{http_code}","httpConnect":"%{http_connect}","httpVersion":"%{http_version}","localIp":"%{local_ip}","localPort":"%{local_port}","numConnects":"%{num_connects}","numRedirects":"%{num_redirects}","proxySslVerifyResult":"%{proxy_ssl_verify_result}","redirectUrl":"%{redirect_url}","remoteIp":"%{remote_ip}","remotePort":"%{remote_port}","scheme":"%{scheme}","size":{"download":"%{size_download}","header":"%{size_header}","request":"%{size_request}","upload":"%{size_upload}"},"speed":{"download":"%{speed_download}","upload":"%{speed_upload}"},"sslVerifyResult":"%{ssl_verify_result}","time":{"appconnect":"%{time_appconnect}","connect":"%{time_connect}","namelookup":"%{time_namelookup}","pretransfer":"%{time_pretransfer}","redirect":"%{time_redirect}","starttransfer":"%{time_starttransfer}","total":"%{time_total}"},"urlEffective":"%{url_effective}"}

输出JSON。

您可以使用curl -v --trace-time将时间戳添加到跟踪/详细输出。这必须在详细模式或跟踪模式下完成才能执行任何操作。

这是Simons答案的修改版本,它使多行输出成为一行。它还引入了当前时间戳,因此更容易跟踪每行输出。

样品格式枪
$ cat time-format.txttime_namelookup:%{time_namelookup} time_connect:%{time_connect} time_appconnect:%{time_appconnect} time_pretransfer:%{time_pretransfer} time_redirect:%{time_redirect} time_starttransfer:%{time_starttransfer} time_total:%{time_total}\n
示例cmd
$ while [ 1 ];do echo -n "$(date) - " ; curl -w @time-format.txt -o /dev/null -s https://myapp.mydom.com/v1/endpt-http; sleep 1; done | grep -v time_total:0
结果
Mon Dec 16 17:51:47 UTC 2019 - time_namelookup:0.004 time_connect:0.015 time_appconnect:0.172 time_pretransfer:0.172 time_redirect:0.000 time_starttransfer:1.666 time_total:1.666Mon Dec 16 17:51:50 UTC 2019 - time_namelookup:0.004 time_connect:0.015 time_appconnect:0.175 time_pretransfer:0.175 time_redirect:0.000 time_starttransfer:3.794 time_total:3.795Mon Dec 16 17:51:55 UTC 2019 - time_namelookup:0.004 time_connect:0.017 time_appconnect:0.175 time_pretransfer:0.175 time_redirect:0.000 time_starttransfer:1.971 time_total:1.971Mon Dec 16 17:51:58 UTC 2019 - time_namelookup:0.004 time_connect:0.014 time_appconnect:0.173 time_pretransfer:0.173 time_redirect:0.000 time_starttransfer:1.161 time_total:1.161Mon Dec 16 17:52:00 UTC 2019 - time_namelookup:0.004 time_connect:0.015 time_appconnect:0.166 time_pretransfer:0.167 time_redirect:0.000 time_starttransfer:1.434 time_total:1.434Mon Dec 16 17:52:02 UTC 2019 - time_namelookup:0.004 time_connect:0.015 time_appconnect:0.177 time_pretransfer:0.177 time_redirect:0.000 time_starttransfer:5.119 time_total:5.119Mon Dec 16 17:52:08 UTC 2019 - time_namelookup:0.004 time_connect:0.014 time_appconnect:0.172 time_pretransfer:0.172 time_redirect:0.000 time_starttransfer:30.185 time_total:30.185Mon Dec 16 17:52:39 UTC 2019 - time_namelookup:0.004 time_connect:0.014 time_appconnect:0.164 time_pretransfer:0.164 time_redirect:0.000 time_starttransfer:30.175 time_total:30.176Mon Dec 16 17:54:28 UTC 2019 - time_namelookup:0.004 time_connect:0.015 time_appconnect:3.191 time_pretransfer:3.191 time_redirect:0.000 time_starttransfer:3.212 time_total:3.212Mon Dec 16 17:56:08 UTC 2019 - time_namelookup:0.004 time_connect:0.015 time_appconnect:1.184 time_pretransfer:1.184 time_redirect:0.000 time_starttransfer:1.215 time_total:1.215Mon Dec 16 18:00:24 UTC 2019 - time_namelookup:0.004 time_connect:0.015 time_appconnect:0.181 time_pretransfer:0.181 time_redirect:0.000 time_starttransfer:1.267 time_total:1.267

我使用上面的方法来捕获上面端点上的缓慢响应。

测量命令执行时间的通用解决方案

Linux/Mac OS/Unix

在Linux,您可以测量使用time命令执行命令所需的时间

time curl https://en.wikipedia.org/wiki/Cat

输出:

ect...</body></html>
real    0m0.565suser    0m0.011ssys     0m0.024s

这里的总时间/响应时间是real时间。

此解决方案是通用的,应该适用于任何Unix命令

time sleep 5

输出:

real    0m5.001suser    0m0.001ssys 0m0.000s

WindowsPowershell

您可以使用测量-命令