通过curl命令判断网络连接的耗时瓶颈
通过curl命令判断网络连接的耗时瓶颈
HTTPS请求的性能优化是网络工程师和运维人员的重要工作内容。本文将详细介绍如何使用curl命令分析HTTPS请求的各个阶段耗时,帮助读者准确掌握每个环节的消耗时间,从而提升网络优化的效率和精度。
一个完整、无任何缓存、未复用连接的HTTPS请求需要经过以下几个阶段:DNS域名解析、TCP握手、SSL/TLS握手、服务器处理、内容传输。
我们把从发出一个请求到收到服务端的响应这个时间,叫RTT(Round-Trip Time)往返时延。如上图所示,一个HTTPS请求共需要5个RTT = 1RTT(域名解析)+ 1RTT(TCP握手)+ 2RTT(SSL/TLS握手)+ 1RTT(HTTP内容请求传输)。
如果网络出现问题,导致一个RTT增加了Nms,那么整个HTTPS请求就会增加5Nms。举个例子,说明接口延迟的计算和影响:假设北京到美国洛杉矶的RTT延迟为190毫秒,我们从北京访问美国洛杉矶的一个HTTPS服务,整个交互过程时延计算是5190+后端业务延时。其中,“5”代表的是HTTPS请求的5个环节,每个环节都需要一个RTT的时间。因为网络延迟始终会受到物理环境的制约,无论使用什么技术、如何优化,950ms的指标将会很难突破,所以*我们的优化策略也是以减少请求环节、链路优化、降低SSL/TLS计算量为主。
HTTPS请求的各个阶段可以使用curl命令进行详细的耗时分析,如下表所示,curl提供了详细的耗时分析选项,这样我们就可以更准确地掌握每一个环节的消耗时间,进一步提升网络优化的效率和精度。
请求阶段 | 释义(单位秒) |
---|---|
time_namelookup | 从请求开始到域名解析完成的耗时 |
time_connect | 从请求开始到TCP三次握手完成耗时 |
time_appconnect | 从请求开始到SSL/TLS/SSH握手完成的耗时,如果未采用SSL/TLS,则此项为0 |
time_pretransfer | 从请求开始到向服务器发送第一个请求开始之前的耗时,这包括针对所涉及的特定协议的所有预传输命令和协商。 |
time_redirect | 重定向时间,包括到内容传输前的重定向的DNS解析、TCP连接、内容传输等时间,如果没有重定向,则此项为0 |
time_starttransfer | 从请求开始到即将接收(还没接收)服务器传过来的第一个字节前的时间,这个时间 = time_pretransfer+服务器处理请求的耗时+一个RTT。 |
time_total | 从请求开始到完成的总耗时 |
业务常关注的性能指标有:域名解析请求耗时、TCP建立耗时、TTFB(Time To First Byte,首字节时间)等,计算方式如下
耗时 | 说明 |
---|---|
域名解析耗时 = time_namelookup | 域名NS及本地LocalDNS解析耗时 |
TCP握手耗时 = time_connect - time_namelookup | 建立TCP连接时间 |
SSL/TLS耗时 = time_appconnect - time_connect | TLS握手以及加解密处理 |
服务器处理请求耗时 = time_starttransfer - time_pretransfer | 服务器处理这个请求消耗了多长时间,其实严格来说是一个RTT+服务器处理请求的时间 |
TTFB = time_starttransfer - time_appconnect | (从客户端的角度看整个请求过程)从服务端和客户端成功成功建立连接到开始到客户端收到第一个字节的耗时 |
总耗时 = time_total |
简单的实践
curl -w '\n 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 time_total=%{time_total}\n' -o /dev/null -s 'https://zm520zyx.com'
第一次测试,输出:
curl -w '\n 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 time_total=%{time_total}\n' -o /dev/null -s 'https://zm520zyx.com'
time_namelookup=1.195716
time_connect=1.248346
time_appconnect=1.901162
time_redirect=0.000000
time_pretransfer=1.901252
time_starttransfer=1.990214
time_total=1.990437
对https://zm520zyx.com测试的结果进行分段统计,结果如下:
耗时 | 说明(单位秒) | 占比 |
---|---|---|
域名解析耗时 = time_namelookup | 1.195716 | 60.07% |
TCP握手耗时 = time_connect - time_namelookup | 0.05263 | 2.64% |
SSL/TLS耗时 = time_appconnect - time_connect | 0.652816 | 32.80% |
服务器处理请求耗时 = time_starttransfer - time_pretransfer | 0.088962 | 4.47% |
TTFB = time_starttransfer - time_appconnect | 0.089052 | 4.47% |
总耗时 = time_total | 1.990437 |
可以很明显的看出,域名解析时间大约占据了总时间的60%,SSL/TLS层耗时则占据了总时间的近32%,光这两项就耗费了差不多90%的时间,而TCP连接大约占据了总时间的2.64%,几乎忽略不计。由此可见,如果我们想要降低HTTPS接口延迟,那么优化域名解析环节和SSL/TLS这两个阶段将会为我们带来显著的性能提升。
紧接着第一次测试结束,我们立即进行第二次测试
curl -w '\n 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 time_total=%{time_total}\n' -o /dev/null -s 'https://zm520zyx.com'
time_namelookup=0.008063
time_connect=0.052308
time_appconnect=0.145729
time_redirect=0.000000
time_pretransfer=0.145810
time_starttransfer=0.224296
time_total=0.224420
我们可以发现,TCP握手时间服务器处理请求的时间还有TTFB都并没有变化多少,主要是是域名解析和SSL/TLS握手花费的时间都大大降低,为什么?因为域名解析会有缓存,同时SSL/TLS握手之后,后面的请求也是会复用已经成功握手的SSL/TLS的状态的,并不是每次请求都重新进行SSL/TLS握手,一段时间之后,再次发起请求,就会发现连接建立的时间又回到了接近2s。
简单总结
如果time_connect(没有SSL/TLS)或者time_appconnect在time_total中的占比很大,说明网络状况不好,延迟很大,导致花费在建立连接上的时间很长。
如果(time_pretransfer – time_appconnect)在time_total中的占比很大,说明建立连接之后,客户端很长时间没有发起请求,说明客户端网络拥挤,不过一般情况下不存在这种情况,time_pretransfer和time_appconnect一般都非常接近。
如果(time_starttransfer - time_pretransfer)在time_total中的占比很大,说明服务端很繁忙,可能是请求太多处理不过来。
本文原文来自CSDN