序: 近期在对阿里云服务器做压力测试,因为webbench ,ab两个工具的压力测试结果和loadrunner,jemer的压测结果相关太远,有上百倍的差距,也是让我们百思不得其解,非常干扰思路.所以对ab,webbench做了简单测试~
工具 | 简介 | 级别 |
---|---|---|
Ab | ab - Apache HTTP server benchmarking tool | 轻量级(比webbench稍强大) |
Webbench | webbench - simple forking web benchmark | 轻量级 |
jmeter | Apache JMeter是Apache组织开发的基于Java的压力测试工具 | 中级 |
loadrunner | HP研发,收费版,但国内早破解泛滥,有window(6G),linux(1.6G)版本 | 重量级/专业级 |
loadrunner几尽为国内测试人员的专用压测工具,他的高度灵活性,数据分析功能,图表展示,用户行为模拟等功能非常强大,专业压测还是以loadrunner为准
这里需再强调下并发的概念,以并发1000为例:
这里的并发1000是针对用户来说,而非服务器每秒并发请求数.即每秒有1000用户(每秒有多次或多种行为)同时对服务器发起请求
-t 指定压测时间
-c 指定并发用户数(非请求数)
-f 零等待服务器响应
如下图做了简单的性能压测.可以看出webbench
模拟一个client
相当于每秒有264.8
个请求,,如果并发压-c 1000clients
,相当于每秒有 1000*264.8
请求 ~想想也是相当凶残~~
-n 设置请求总数
-c 设置并发client数量
如图可以看出ab
模拟一个client
相当于每秒有268.04
有个请求,,如果并发压-c 1000clients
,相当于每秒有1000*268.04
请求
业界一直认为loadrunner是最专业的,ab,webbench
相比之下哪里不专业了呢,测试同学的说法是webbench,ab只进行了2次握手就离开继续下一次新请求,这里个人觉得不靠谱,我们模拟一次测试验证下.这里有遇到一个问题,如果去抓取一个用户数据包.ab
的功能就有大显身手了,只压一个数据包.
ab -n 1 -c 1 -k 'http://optimize.piaotai.com/index.php'
同时在被压测机抓包
tcpdump -i eth0 ip host web-yv4 and port ! 22
tcpdump -i eth0 ip host 10.169.11.99 and 10.171.215.112 and dst port 80
TCP Flag | Flag in tcpdump | Flag Meaning |
---|---|---|
SYN | s | Syn packet, a session establishment request. The first part of any TCP connection. |
ACK | ack | Ack packet, used to acknowledge the receipt of data from the sender. May appear in conjunction with other flags. |
FIN | f | Finish flag, used to indicate the sender’s intention to terminate the connection to the receiving host. |
RESET | r | Indicates the sender’s intention to immediately abort the existing connection. |
PUSH | p | Signals the immediate push of data from the sending host to the receiving host. For interactive applications such as telnet, the main issue is the quickest response time, which this “push” flag signals. |
URGENT | urg | Urgent data should take precedence over other data. For example, a Ctrl-C to terminate a FTP download. |
Placeholder | . | If the connection does not have a syn, finish, reset, or push flag set, this placefolder flag will be found after the destination port. Note that it also appears in conjunction with the ack flag. |
SYN: 表示建立连接, FIN: 表示关闭连接, ACK: 表示响应, PUSH: 表示有 DATA数据传输, RST: 表示连接重置。 码即tcp标志位,有6种标示:
如下范例是一条完整的http数据流分析:
19:28:31.951855 IP 58.246.240.122.63798 > 112.124.45.184.http: Flags [S], seq 3672193843, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
//client58.246.240.122通过63798向WebServer 112.124.45.184发起一条序列号为3672193843,win size为8192,没有数据的SYNC请求
//第一次握手
19:28:31.951889 IP 112.124.45.184.http > 58.246.240.122.63798: Flags [S.], seq 38994743, ack 3672193844, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
//WerServer回应ack收到并发送一条seq为38994743
//第二次握手
19:28:32.207276 IP 58.246.240.122.63801 > 112.124.45.184.http: Flags [S], seq 3586463872, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
//(应该)前两次握手失败,重新发起一次新一轮握手请求
//第一次握手
19:28:32.207304 IP 112.124.45.184.http > 58.246.240.122.63801: Flags [S.], seq 1159592009, ack 3586463873, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
//第二次握手
19:28:32.361241 IP 58.246.240.122.63798 > 112.124.45.184.http: Flags [.], ack 1, win 16425, length 0
//第三次握手,三次握手至此结束
//client回应收到
19:28:32.361403 IP 58.246.240.122.63798 > 112.124.45.184.http: Flags [P.], seq 1:350, ack 1, win 16425, length 349
//client发起ack应答并PUSH一条长度为349大小数据的请求
19:28:32.361419 IP 112.124.45.184.http > 58.246.240.122.63798: Flags [.], ack 350, win 123, length 0
//webserver应答seq为350的请求.
19:28:32.361945 IP 112.124.45.184.http > 58.246.240.122.63798: Flags [P.], seq 1:241, ack 350, win 123, length 240
//webserver应答并PUSH一条长度为240大小的数据
19:28:32.383558 IP 58.246.240.122.63801 > 112.124.45.184.http: Flags [.], ack 1, win 16425, length 0
//client应答ack1表示收到数据
19:28:32.613585 IP 58.246.240.122.63798 > 112.124.45.184.http: Flags [.], ack 241, win 16365, length 0
//client应答ack241表示收到数据
19:28:37.384847 IP 58.246.240.122.63801 > 112.124.45.184.http: Flags [F.], seq 1, ack 1, win 16425, length 0
//client应答ack1并起一条seq为1的FIN断开请求
//第一次挥手
//tcp状态置为timewait状态
19:28:37.384949 IP 112.124.45.184.http > 58.246.240.122.63801: Flags [F.], seq 1, ack 2, win 115, length 0
//webserver回应收到seq为1的请求并也发起一条seq为1的FIN断开请求
//第二次挥手
//tcp状态置为close_wait状态
19:28:37.445546 IP 58.246.240.122.63801 > 112.124.45.184.http: Flags [.], ack 2, win 16425, length 0
//client应答表示收到seq为1(这里的ack=1是syn+1)的请求
//第三次挥手
//tcp状态置为closed状态
19:28:42.418048 IP 58.246.240.122.63798 > 112.124.45.184.http: Flags [.], seq 349:350, ack 241, win 16365, length 1
19:28:42.418073 IP 112.124.45.184.http > 58.246.240.122.63798: Flags [.], ack 350, win 123, options [nop,nop,sack 1 {349:350}], length 0
//第四次挥手 //server发起一
我们具体来看下ab/webbench访问的过程请求,我们会发现是webserver先发起断开请求,
Ok~
至此, webbench/ab
和 loadrunner
的用户行为分析完毕,大家可能也有留意到webserver
在这过程中断开请求的行为是不一样的.粗心的同学就会有下文的悲剧,满世界在找webserver
端有TIMEWAIT
的问题~~
对于压测工具,了解到如上程度也差不多了 但要想更深入,下文必看
~~
上面的这些介绍,相信对压测工具已经有所了解,但我们压测过程中遇到的问题却远没有解决.
大家知道,nginx
在针对请求如果开启keepalived_timeout
,在超时范围内是不会主动断开请求连接, 且一般是请求发起方会先发起FIN
主动断开连接,那我们服务器上那么多的TIMEWAIT
是哪里来的呢?
刚开始压测就发现服务器有近 1.3w 的TIME-WAIT
状态.而且这些状态不是后端php的,是80端口的
我们可以看出是webserver主动发起FIN包断开连接.这个是正常的
还是webserver主动断开请求~,
这个也太不正常了,难道是 keepalived
一直没有生效或者是nginx
重启失败(安全期间一直用的是restart,没有用reload)?
经如上几轮测试,大家应该可以认定keepalived是生效的
Tcp
抓取ab/webbench
的数据包分析也是有keepalived
包头,但keepalived
是不生效的,但为什么不生效呢??…
虽然问题根源没有找到,但经过测试,我们最少发现
久查无果,也是相当伤脑筋. 大师说:在没有思路的时候多出去走走.
果不其然,放松之后头脑也慢慢变清醒,有一个关键事件一直没有关注~.. 日志!!!
一直沉浸在问题数据流层面,同时也是因为压测数据量很大,对nginx日志的关注度略有降低,迅速拎来日志粗看就发现问题了~
webbench/ab
和loadrunner
访问请求是完全不一样的.
webbench/ab用的是 http 1.0
的协议, loadrunner走的是http1.1
的协议
Ab/webbench
是否支持http1.1协议呢?~
再看 webbench/ab help
说明
SO~
=== ➔ 专业的压测工具还是用loadrunner吧~~~
那http1.0和http1.1究竟有什么区别呢,导致服务器的行为有如此大的区别?
一个 WEB 站点每天可能要接收到上百万的用户请求,为了提高系统的效率,HTTP 1.0 规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。
在tcp/ip 3次握手4次挥手中,主动发送FIN状态要求断开连接方TCP状态会被置为 TIMEWAIT
状态,被断开方TCP
状态会被置为CLOSEWAIT
状态.正因为这样的原因,所以每次压测都会出现在keepalived-time
超时时长内webserver
就会有TIMEWAIT
状态.为了验证,我们改用loadrunner来测试.
再来看服务器各状态汇总,在高并发状态下,每种状态都有
在一次http压包测中我们发现服务器请求中http请求数远多于tcp/ip协议请求数.这个是什么原因呢?难道loadrunner访问模拟的是浏览器有cache的这种方式,只有第一次访问是全新访问,后面的访问全部都是f5刷新方式的访问?
从上面这个图我们也可以看到,f5的请求和ctrl+f5的请求是有很大区别的。对服务器的压力也一定相关巨大!并发的概念中是每次请求都是全新请求还是第一次请求是全新请求就可以了?