通过curl命令分析http性能
通常HTTP的性能分析是通过浏览器的开发者工具进行查看,但这种方式只能通过图形页面进行查看。如果想做性能监控或者在命令行下分析,可以通过curl命令来统计各阶段的耗时。我们先来看看一个HTTP请求的过程:
(图片来自cloudflare)
每次http请求经过这些过程: 客户端发起请求-->DNS解析-->TCP连接-->SSL等协议握手-->服务器处理-->内容传输-->完成
查看curl 命令的手册,curl命令支持以下阶段的时间统计:
- time_namelookup : 从请求开始到DNS解析完成的耗时
- time_connect : 从请求开始到TCP三次握手完成耗时
- time_appconnect : 从请求开始到TLS握手完成的耗时
- time_pretransfer : 从请求开始到向服务器发送第一个GET请求开始之前的耗时
- time_redirect : 重定向时间,包括到内容传输前的重定向的DNS解析、TCP连接、内容传输等时间
- time_starttransfer : 从请求开始到内容传输前的时间
- time_total : 从请求开始到完成的总耗时
我们常关注的HTTP性能指标有:
- DNS请求耗时 : 域名的NS及本地使用DNS的解析速度
- TCP建立耗时 : 服务器网络层面的速度
- SSL握手耗时 : 服务器处理HTTPS等协议的速度
- 服务器处理请求时间 : 服务器处理HTTP请求的速度
- TTFB : 服务器从接收请求到开始到收到第一个字节的耗时
- 服务器响应耗时 :服务器响应第一个字节到全部传输完成耗时
- 请求完成总耗时
注意: 如果想分析HTTP性能的瓶颈,不建议使用带有重定向的请求进行分析,重定向会导致建立多次TCP连接或多次HTTP请求,多次请求的数据混在一起,数据不够直观,因此 time_redirect 对实际分析意义不大。
其中的运算关系:
- DNS请求耗时 = time_namelookup
- TCP三次握手耗时 = time_connect - time_namelookup
- SSL握手耗时 = time_appconnect - time_connect
- 服务器处理请求耗时 = time_starttransfer - time_pretransfer
- TTFB耗时 = time_starttransfer - time_appconnect
- 服务器传输耗时 = time_total - time_starttransfer
- 总耗时 = time_total
用curl命令统计以上时间:
curl -w '\ntime_namelookup=%{time_namelookup}\ntime_connect=%{time_connect}\ntime_appconnect=%{time_appconnect}\ntime_redirect=%{time_redirect}\ntime_pretransfer=%{time_pretransfer}\ntime_starttransfer=%{time_starttransfer}\ntime_total=%{time_total}\n\n' -o /dev/null -s -L 'https://www.nixops.me/'
以上内容不够直观,curl -w参数支持模板,新建一个文件timing.txt,内容如下:
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
使用模板在执行一次:
curl -w "@timing.txt" -o /dev/null -s -L 'https://www.nixops.me/'
将上述功能生成脚本stat.sh
#!/bin/bash
#author : will
#website: https://www.nixops.me
Default_URL=https://www.nixops.me
URL=${1:-$Default_URL}
Result=`curl -o /dev/null -s $URL \
-w \
'time_namelookup=%{time_namelookup}
time_connect=%{time_connect}
time_appconnect=%{time_appconnect}
time_redirect=%{time_redirect}
time_pretransfer=%{time_pretransfer}
time_starttransfer=%{time_starttransfer}
time_total=%{time_total}
'`
declare $Result
curl_timing(){
printf "\e[92mcURL Timing: \e[0m\n"
for i in $Result
do
IFS='='
printf "\e[96m%18s \e[0m: %10s \n" $i
done
}
stat_timing(){
Result_TCP=`printf "%.6f" $(echo $time_connect - $time_namelookup |bc -l)`
Result_TLS=`printf "%.6f" $(echo $time_appconnect - $time_connect |bc -l)`
Result_Server=`printf "%.6f" $(echo $time_starttransfer - $time_pretransfer |bc -l)`
Result_TTFB=`printf "%.6f" $(echo $time_starttransfer - $time_appconnect |bc -l)`
Result_Transfer=`printf "%.6f" $(echo $time_total - $time_starttransfer |bc -l)`
printf "\n\e[92mResource Timing: \e[0m\n"
printf "\e[96m%18s \e[0m: %.6f \n" "DNS Lookup" $time_namelookup
printf "\e[96m%18s \e[0m: %.6f \n" "TCP Connection" $Result_TCP
if [ `echo "$time_appconnect == 0"|bc` -eq 0 ]
then
printf "\e[96m%18s \e[0m: %.6f \n" "TLS Handshake" $Result_TLS
fi
printf "\e[96m%18s \e[0m: %.6f \n" "Server Processing" $Result_Server
printf "\e[96m%18s \e[0m: %.6f \n" "TTFB" $Result_TTFB
printf "\e[96m%18s \e[0m: %.6f \n" "Content Transfer" $Result_Transfer
printf "\e[96m%18s \e[0m: %.6f \n" "Finish" $time_total
}
curl_timing
stat_timing
执行一下:
# ./stat.sh https://www.baidu.com
cURL Timing:
time_namelookup : 0.004087
time_connect : 0.006480
time_appconnect : 0.022001
time_redirect : 0.000000
time_pretransfer : 0.022026
time_starttransfer : 0.025635
time_total : 0.025658
Resource Timing:
DNS Lookup : 0.004087
TCP Connection : 0.002393
TLS Handshake : 0.015521
Server Processing : 0.003609
TTFB : 0.003634
Content Transfer : 0.000023
Finish : 0.025658
从上述结果,就可以直观的分析出http各阶段的耗时,方便我们进行性能瓶颈。
参考文章:
https://cizixs.com/2017/04/11/use-curl-to-analyze-request/
https://blog.cloudflare.com/a-question-of-timing/
https://curl.se/docs/manpage.html
https://github.com/reorx/httpstat
[...]通过curl命令分析http性能[...]