前言
上周,我方的一个客户反馈,访问我们的接口,平均耗时在2s以上。但是我方对请求进入,和请求返回,整个过程都有监控,我方的耗时基本在50ms以内,非常快。
后来了解到,客户从广东访问到我方上海,公网来访问我方。那么就建议去检测,DNS耗时,TCP建立的耗时等。理论上,长距离的公网,网络延迟就非常高。遂建议使用CURL去检查。结果果然如猜想,在TCP建立的耗时就很久。
进入正题,这篇文章主要介绍使用CURL检测Client端发起的HTTP请求,各个阶段的时间。
第一、HTTP请求的过程介绍
一个HTTP请求,涉及多个阶段
1、DNS解析域名
2、请求从Clinet路由至Server,Clinet与Server建立TCP连接
3、如果使用了HTTPS,还涉及SSL连接的建立
4、server开始准备数据
开始逻辑计算、调后端接口、查数据库缓存等
5、server开始传递数据
数据准备完成,开始给client传数据
6、数据传输完毕
7、整个过程可能还涉及多次重定向
第二、关于CURL的介绍
CURL是利用URL语法在命令行方式下工作的开源数据传输工具。
支持:DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, Telnet and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, HTTP/2, cookies, user+password authentication (Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos), file transfer resume, proxy tunneling 等
最新版的curl稳定版为7.55.1(截止20170817)
源代码:https://github.com/curl/curl
第三:用CURL检测Clinet侧发起的HTTP请求各阶段时间,简要说明
1、TCP建立连接的耗时:CONNECT-NAMELOOKUP
2、建立TCP连接到server返回client第一个字节的时间:
STARTTRANSFER-CONNECT
3、SERVER处理数据的时间:
可以用STARTTRANSFER - PRETRANSFER计算得到
4、CLIENT接收数据的耗时(开始接收至接收完成):
TOTAL-STARTTRANSFER
第四、例子:
curl -o /dev/null -s -w time_namelookup:"\t"%{time_namelookup}"\n"time_connect:"\t\t"%{time_connect}"\n"time_appconnect:"\t"%{time_appconnect}"\n"time_pretransfer:"\t"%{time_pretransfer}"\n"time_starttransfer:"\t"%{time_starttransfer}"\n"time_total:"\t\t"%{time_total}"\n"time_redirect:"\t\t"%{time_redirect}"\n" https://www.yqb.com/
1、DNS解析耗时:0.008s
2、TCP建立连接的耗时:0.059-0.008=0.051s
3、SSL握手完成耗时:0.228-0.059=0.169s
169ms,多了一层SSL还是很耗时的
4、server处理数据的时间:0.287-0.228=0.059
59ms,说明服务器处理很快
5、总体的耗时:0.228s
6、整个过程没有redirect,所以redirect的耗时为0
再举一例:
服务器处理数据的耗时:2.305-0.014=2.291s
这就说明server端的性能是值得研究的。
对于server端而言,有需要分析它的耗时:
防火墙->负载均衡->应用->缓存和DB
需要深入去分析这个时间消耗在哪个环节,有针对性的优化。
第五、详细说明
NAMELOOKUP:从开始计算,域名解析完成的耗时
CURLINFO_NAMELOOKUP_TIME. The time it took from the start until the name resolving was completed.
CONNECT:从开始计算,TCP建立完成的耗时
CURLINFO_CONNECT_TIME. The time it took from the start until the connect to the remote host (or proxy) was completed.
APPCONNECT:从开始计算,应用层(SSL,在TCP之上的应用层)连接/握手完成的耗时
CURLINFO_APPCONNECT_TIME. The time it took from the start until the SSL connect/handshake with the remote host was completed. (Added in in 7.19.0)
PRETRANSFER:从开始计算,准备开始传输数据的耗时
CURLINFO_PRETRANSFER_TIME. The time it took from the start until the file transfer is just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.
STARTTRANSFER:从开始计算,开始传输数据的耗时(libcurl接收到第一个字节)
CURLINFO_STARTTRANSFER_TIME. The time it took from the start until the first byte is received by libcurl.
TOTAL:总的耗时
CURLINFO_TOTAL_TIME. Total time of the previous request.
REDIRECT:整个过程重定向的耗时,如果整个过程没有重定向,这个时间为0
CURLINFO_REDIRECT_TIME. The time it took for all redirection steps include name lookup, connect, pretransfer and transfer before final transaction was started. So, this is zero if no redirection took place.
另:python也有一个pycurl模块,大家可以尝试。
参考:
https://curl.haxx.se/libcurl/c/curl_easy_getinfo.html