在测试http服务时,通常会使用curl想服务器发起http请求,curl会模拟浏览器的请求,也会帮助你与服务器建立tls/ssl连接。有时我们希望得到请求过程中的耗时,来优化客户端的体验,这时一般会用到curl的-w参数。

    curl的统计指标
    根据curl手册中的说明,curl允许我们在-w参数后指定一个文本,文本中可以包含%{MACRO}形式的参数,curl会将实际的请求耗时,替换到这些宏当中。

    虽然也有一些文章描述该功能,但是对于耗时这块往往描述的不明确,甚至是错误的,为了验证耗时的真正含义,我使用-w参数加wireshark抓包验证了一下,整理了常见的耗时相关统计值和说明如下:

    统计值 说明
    time_namelookup 域名解析耗时
    time_connect TCP连接耗时
    time_appconnect TLS/SSL连接耗时
    time_pretransfer 发送预处理耗时
    time_starttransfer 数据传输及服务端处理耗时
    time_redirect 重定向耗时
    time_total 总体耗时
    每一个参数都包含前面所有参数的耗时,这样说不太容易理解,上图比较好说明:

    所以time_connect的含义是TCP建立连接时间,而实际上,它包含了域名解析的时间,所以如果仅希望获得TCP的三次握手耗时,应当用time_connect - time_namelookup,后面的参数也是一样。如果希望获得数据往返传输和服务器处理的耗时,就需要用time_starttransfer - time_pretransfer。

    实践
    来看下实际的示例,首先来写一个包含参数的文本文件

    \n
    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

    将文件保存为curl.txt,使用curl模拟请求www.baidu.com,-w参数指定该文本文件

    $ curl http://www.baidu.com/ -w ‘@curl.txt’
    time_namelookup: 0.010484
    time_connect: 0.023659
    time_appconnect: 0.000000
    time_pretransfer: 0.023833
    time_redirect: 0.000000
    time_starttransfer: 0.039934
    1
    2
    3
    4
    5
    6
    7
    由于没有指定https协议,所以time_appconnect这块的时间为0。而TCP建立连接的时间=0.023659 - 0.010484 = 0.013175秒,同理,网络传输和服务器处理耗时为0.016101秒。
    这些时间有助于发现客户端体验方面的性能问题,进一步进行优化。

    更丰富的参数
    当然curl的-w除了性能参数,还支持很多其他参数,如果你图省事,也可以直接用%{json}这个参数,他会以json形式将-w参数支持的所有值都输出出来

    $ curl -s http://www.baidu.com/ -w ‘%{json}’ -o /dev/null | jq
    {
    “content_type”: “text/html”,
    “errormsg”: null,
    “exitcode”: 0,
    “filename_effective”: “/dev/null”,
    “ftp_entry_path”: null,
    “http_code”: 200,
    “http_connect”: 0,
    “http_version”: “1.1”,
    “local_ip”: “172.16.120.205”,
    “local_port”: 59399,
    “method”: “GET”,
    “num_connects”: 1,
    “num_headers”: 11,
    “num_redirects”: 0,
    “proxy_ssl_verify_result”: 0,
    “redirect_url”: null,
    “referer”: null,
    “remote_ip”: “180.101.49.11”,
    “remote_port”: 80,
    “response_code”: 200,
    “scheme”: “HTTP”,
    “size_download”: 2381,
    “size_header”: 400,
    “size_request”: 77,
    “size_upload”: 0,
    “speed_download”: 52439,
    “speed_upload”: 0,
    “ssl_verify_result”: 0,
    “time_appconnect”: 0,
    “time_connect”: 0.026548,
    “time_namelookup”: 0.011452,
    “time_pretransfer”: 0.026612,
    “time_redirect”: 0,
    “time_starttransfer”: 0.045227,
    “time_total”: 0.045405,
    “url”: “http://www.baidu.com/“,
    “url_effective”: “http://www.baidu.com/“,
    “urlnum”: 0,
    “curl_version”: “libcurl/7.79.1 (SecureTransport) OpenSSL/1.1.1l zlib/1.2.11 brotli/1.0.9 zstd/1.5.0 libidn2/2.3.2 libssh2/1.10.0 nghttp2/1.46.0 librtmp/2.3 OpenLDAP/2.5.7”
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    这次-w没有指定文件,而是直接将期望输出的变量写在-w参数中,因此不需要指定@符号。而jq命令用来格式化输出json,-o /dev/null是为了不让返回数据干扰json统计数据的输出。
    ————————————————
    版权声明:本文为CSDN博主「一只coding猪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_44446512/article/details/121376195