【问题标题】:How do I measure request and response times at once using cURL?如何使用 cURL 一次测量请求和响应时间?
【发布时间】:2013-08-15 10:34:52
【问题描述】:

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

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

我的示例请求如下所示:

curl -X POST -d @file server:port

我目前在 Linux 中使用 time 命令测量这个:

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

不过,时间命令仅测量 时间 - 这并不是我想要的。

有什么方法可以使用cURL 测量请求和响应时间?

【问题讨论】:

    标签: curl time upload download measure


    【解决方案1】:

    来自这篇精彩的博文...https://blog.josephscott.org/2011/10/14/timing-details-with-curl/

    cURL 支持请求详细信息的格式化输出(请参阅the cURL manpage for details,在-w, –write-out <format> 下)。出于我们的目的,我们将只关注提供的时间细节。以下时间以为单位。

    1. 新建一个文件,curl-format.txt,然后粘贴进去:

           time_namelookup:  %{time_namelookup}s\n
              time_connect:  %{time_connect}s\n
           time_appconnect:  %{time_appconnect}s\n
          time_pretransfer:  %{time_pretransfer}s\n
             time_redirect:  %{time_redirect}s\n
        time_starttransfer:  %{time_starttransfer}s\n
                           ----------\n
                time_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.001s
          time_connect:  0.037s
       time_appconnect:  0.000s
      time_pretransfer:  0.037s
         time_redirect:  0.000s
    time_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}\n
           time_connect:  %{time_connect}\n
        time_appconnect:  %{time_appconnect}\n
       time_pretransfer:  %{time_pretransfer}\n
          time_redirect:  %{time_redirect}\n
     time_starttransfer:  %{time_starttransfer}\n
                        ----------\n
             time_total:  %{time_total}\n
    EOF
    

    调用方式与别名相同:

    curltime wordpress.org
    

    制作 Windows 快捷方式(又名 BAT 文件)

    将此命令放在 CURLTIME.BAT 中(与 curl.exe 位于同一文件夹中)

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

    那么你可以简单地调用...

    curltime wordpress.org
    

    【讨论】:

    • 很棒的答案。谢谢。我必须做的一件事是添加\n 以在文本文件中换行
    • 在windows BAT文件中它只发送第一个参数,改为这个来传递所有参数并禁用echo它自己的命令:@curl -w "@%~dp0curl-format.txt" -o NUL -s %*很好的答案
    • 谢谢@udoh,我已经更新了答案以包含它。
    • 优秀的答案。我如何还包括 curl 发起请求的当前日期+时间?
    • 对于 Linux,我创建了一个 dotfile 和一个别名,它似乎运行良好:alias curltime="curl -w \"@$HOME/.curl-format.txt\" -o NUL -s "。可能也适用于 MacOS。
    【解决方案2】:

    答案如下:

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

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

    【讨论】:

    • 添加新行更利于用户体验:"\n%{time_connect}:%{time_starttransfer}:%{time_total}\n"
    • 对我来说,没有引号就行不通。我建议在指定格式时添加引号 /h/a/c/haproxy # ❯❯❯ curl -w "%{time_total}\n" google.com -o /dev/null -s 0.055
    • @Geek 在静默模式下运行时显示错误通常是有意义的 (-sS)。
    【解决方案3】:

    选项 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.020033s
    TTFB: 0.417907s
    Total: 0.435486s
    

    参考:Get response time with curl

    【讨论】:

      【解决方案4】:

      以下内容的灵感来自西蒙的回答。它是独立的(不需要单独的格式文件),非常适合包含在 .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,125000s
            connect:  0,250000s
         appconnect:  0,609000s
        pretransfer:  0,609000s
           redirect:  0,000000s
      starttransfer:  0,719000s
      -------------------------
              total:  0,719000s
      

      【讨论】:

        【解决方案5】:

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

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

        用法:

        > perf stackoverflow.com
        0.521 + 0.686 = 1.290
        

        【讨论】:

        • 我使用了一个变量来显示在测量时间内下载的字节数:curl -o /dev/null -s -w "time_total: %{time_total} sec\nsize_download: %{size_download} bytes\n" https://www.google.com
        【解决方案6】:

        如果你想分析或总结延迟可以试试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:        gws
        Server Hostname:        www.google.com
        Server Port:            80
        
        Document Path:          /
        Document Length:        12419 bytes
        
        Concurrency Level:      1
        Time taken for tests:   10.700 seconds
        Complete requests:      100
        Failed requests:        97
           (Connect: 0, Receive: 0, Length: 97, Exceptions: 0)
        Total transferred:      1331107 bytes
        HTML transferred:       1268293 bytes
        Requests 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   max
        Connect:       20   22   0.8     22      26
        Processing:    59   85 108.7     68     911
        Waiting:       59   85 108.7     67     910
        Total:         80  107 108.8     90     932
        
        Percentage of the requests served within a certain time (ms)
          50%     90
          66%     91
          75%     93
          80%     95
          90%    105
          95%    111
          98%    773
          99%    932
         100%    932 (longest request)
        

        【讨论】:

        • 比其他答案更简单。完全忘记了这个命令!
        • 这是一个绝妙的答案。 ab 可以轻松接受许多与 curl 相同的标志,例如-H 用于标题。我使用此命令对第三方 API 的响应时间进行基准测试(在 Authorization 标头中提供不记名令牌)。工作出色。
        【解决方案7】:

        另一种方法是像这样配置~/.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.com
        HTTP/2 301
        location: https://www.google.com/
        content-type: text/html; charset=UTF-8
        date: Mon, 04 Mar 2019 08:02:43 GMT
        expires: Wed, 03 Apr 2019 08:02:43 GMT
        cache-control: public, max-age=2592000
        server: gws
        content-length: 220
        x-xss-protection: 1; mode=block
        x-frame-options: SAMEORIGIN
        alt-svc: quic=":443"; ma=2592000; v="44,43,39"
        
        
        
        ==== cURL measurements stats ====
        total: 0.211117 seconds
        size: 0 bytes
        dnslookup: 0.067179 seconds
        connect: 0.098817 seconds
        appconnect: 0.176232 seconds
        redirect: 0.000000 seconds
        pretransfer: 0.176438 seconds
        starttransfer: 0.209634 seconds
        downloadspeed: 0.000 byte/sec
        uploadspeed: 0.000 byte/sec
        

        【讨论】:

        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

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

          ./hey https://google.com -more
          Summary:
            Total:    3.0960 secs
            Slowest:  1.6052 secs
            Fastest:  0.4063 secs
            Average:  0.6773 secs
            Requests/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 secs
            25% in 0.4505 secs
            50% in 0.4838 secs
            75% in 1.2181 secs
            90% in 1.2869 secs
            95% in 1.3384 secs
            99% in 1.4085 secs
          
          Details (average, fastest, slowest):
            DNS+dialup:    0.1150 secs, 0.0000 secs, 0.4849 secs
            DNS-lookup:    0.0032 secs, 0.0000 secs, 0.0319 secs
            req write:     0.0001 secs, 0.0000 secs, 0.0007 secs
            resp wait:     0.2068 secs, 0.1690 secs, 0.4906 secs
            resp read:     0.0117 secs, 0.0011 secs, 0.2375 secs
          
          Status code distribution:
            [200] 200 responses
          

          参考文献

          【讨论】:

            【解决方案10】:

            就命令行而言,另一个可能是最简单的选项是添加内置的--trace-time 选项:

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

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

            $ curl https://www.google.com --trace-time -v -o /dev/null
            13:29:11.148734 * Rebuilt URL to: https://www.google.com/
              % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                             Dload  Upload   Total   Spent    Left  Speed
              0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     013:29:11.149958 *   Trying 172.217.20.36...
            13:29:11.149993 * TCP_NODELAY set
            13:29:11.163177 * Connected to www.google.com (172.217.20.36) port 443 (#0)
            13:29:11.164768 * ALPN, offering h2
            13:29:11.164804 * ALPN, offering http/1.1
            13:29:11.164833 * successfully set certificate verify locations:
            13:29:11.164863 *   CAfile: none
              CApath: /etc/ssl/certs
            13: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-POLY1305
            13:29:11.204451 * ALPN, server accepted to use h2
            13:29:11.204483 * Server certificate:
            13:29:11.204520 *  subject: C=US; ST=California; L=Mountain View; O=Google LLC; CN=www.google.com
            13:29:11.204555 *  start date: Oct  2 07:29:00 2018 GMT
            13:29:11.204585 *  expire date: Dec 25 07:29:00 2018 GMT
            13: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 G3
            13:29:11.204701 *  SSL certificate verify ok.
            13:29:11.204754 * Using HTTP2, server supports multi-use
            13: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=0
            13: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/2
            13:29:11.205104 > Host: www.google.com
            13:29:11.205104 > User-Agent: curl/7.61.0
            13: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 200 
            13:29:11.251962 < date: Fri, 19 Oct 2018 10:29:11 GMT
            13:29:11.251998 < expires: -1
            13:29:11.252046 < cache-control: private, max-age=0
            13:29:11.252085 < content-type: text/html; charset=ISO-8859-1
            13:29:11.252119 < p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."
            13:29:11.252160 < server: gws
            13:29:11.252198 < x-xss-protection: 1; mode=block
            13:29:11.252228 < x-frame-options: SAMEORIGIN
            13:29:11.252262 < set-cookie: 1P_JAR=2018-10-19-10; expires=Sun, 18-Nov-2018 10:29:11 GMT; path=/; domain=.google.com
            13: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; HttpOnly
            13:29:11.252336 < alt-svc: quic=":443"; ma=2592000; v="44,43,39,35"
            13:29:11.252368 < accept-ranges: none
            13:29:11.252408 < vary: Accept-Encoding
            13:29:11.252438 < 
            13:29:11.252473 { [5 bytes data]
            100 12215    0 12215    0     0   112k      0 --:--:-- --:--:-- --:--:--  112k
            13:29:11.255674 * Connection #0 to host www.google.com left intact
            

            【讨论】:

            • 这实际上是一个很好的答案,它可能适合人们在这里寻找的大多数用例。其他答案非常适合彻底、深入的解决方案,但这对于快速检查往返时间很有用。
            • 谢谢@ChrisVandevelde。是的,我知道有这样的“东西”(以前使用过这个参数),然后我用谷歌搜索了这个 SO 帖子并找到了更复杂的形式,但是......我觉得还有另一种方式. :) 就像你说的那样,它的简单性很简洁,有时对于更简单的用例来说已经足够了。
            【解决方案11】:

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

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

            【讨论】:

              【解决方案12】:

              这是您可以与-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。

              【讨论】:

              • 添加 \n 有助于区分正文不以换行符结尾的时间:curl -w '\n{"contentType":"..."}...
              【解决方案13】:

              这是一个重复访问同一服务器的 Bash 单线:

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

              【讨论】:

                【解决方案14】:

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

                示例格式文件
                $ cat time-format.txt
                time_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.666
                Mon 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.795
                Mon 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.971
                Mon 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.161
                Mon 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.434
                Mon 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.119
                Mon 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.185
                Mon 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.176
                Mon 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.212
                Mon 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.215
                Mon 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
                

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

                【讨论】:

                  猜你喜欢
                  • 2014-11-09
                  • 1970-01-01
                  • 2013-03-18
                  • 2017-09-01
                  • 1970-01-01
                  • 2021-11-03
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-08-08
                  相关资源
                  最近更新 更多