在做性能测试的时候,最基本也是必需的一个工具就是所谓的load generator,说白了就是用来产生测试流量的工具,或者是大的工具中的一个模块。Load Generator是LoadRunner的叫法,因为它用得比较广,所以这个名字也广为人知了。
更清楚一点,举个例子,为了模拟大量的HTTP客户端来向server发起请求,你可以请一群人,起几十个IE, 然后喊口令请大家一起点,但是基本上这样不work(不要问我原因,不信可以试一下,我倒是真在某处见过有单位这么干的)。实际中大家可能会用LoadRunner/JMeter/WAS等工具来模拟很多的并发用户,产生大的流量。这个时候,上面的工具就是load generator了,当然它可能也同时被用作controller或者resource monitor。
HTTP可能不是个很好的例子,因为HTTP load generator满世界都是,要求不高的话找个free的很容易,谁叫web的performance最普遍呢。如果是其他协议,可能就没有这么普通了,或者说能满足实际项目要求的就更少了,对冷门的或者私有的协议就更惨一点。
既然没有很好的现成的,另一个途径就是自己写一个,咱是QA,但也是programmer,写代码也是分内之事哈。而且现在的很多高级语言开发起来快得让你自己都觉得不好意思,似乎得来太容易。
最近在看公司里面一个用Ruby写的automation的framework,于是顺便study了下Ruby,然后就写了个SMTP client。其实team倒是不缺这个,不过当是POC了。
(为了保留Eclipse的颜色,看起来舒服点,就用snapshot了,反正代码少到不值得copy :) )
区区三十行代码就可以实现一个多线程的SMTP client,从15K.eml这个文件中读取mail header和boby,然后发出去。
如果不嫌弃的话,理论上这个就可以用来作为SMTP performance测试的load generator,然后可以看你的MTA或者Mail server每秒可以处理多少封这种15KB size的纯文本mail,听起来有点意义。
世界真美好,我一边在感叹Ruby的简洁和快速。不过既然是load generator,自然要去看看这个小generator的极限能力是怎样,就是看它能跑多快。之前对Ruby的性能也不了解。
测试环境很简单,在本地起一个类似postfix smtp-sink的fake的MTA, 称它fake是因为它收到mail之后全部在内存丢弃,所以没有IO的压力,相比真的mail server要快很多很多倍,而且从client的角度它是一个正常的MTA。之前试过这个fake的MTA在一个Thinkpad T60上可以把1Gbps 带宽用满,而且自己CPU usage还不是太高。说了这么多,意思就是说测试中Mail server不会是bottleneck, 所以可以看出client的极限。
HW: PC, Core 2 E6550 @2.33 GHz, 2GB RAM.
15K的sample是一次读入内存,后面不会有大量的IO。
测试的结果是如果单线程发1000封的话,大概可以到 50 msg/s, 2个线程的话可以上到80左右,再增加就上不去了,可能因为就两个核。理论上应该可以更高,这里先放一边。
算算其实也相当快了,80 msg/s = 288,000 msg/hour = 6,912,000 msg/day
全世界每天收到这么多mail的公司应该不是很多了。
当然你要说和pure C的client比,那还是要差不少,pure C的至少200+,不过写起来就要复杂很多了,主要是socket和multi thread的处理。
大概是因为常做系统稳定性测试的原因,本能的我想看看这个工具在大压力长时间运行的时候稳定性如何。还是10个thread,但是把循环次数加大。结果出问题了。
注:代码注释调整过,所以行号可能对不上。
连着试了好几次,每次都是到几千封的时候出错,发往smtp-sink也试过,还是一样。从stack看起来是在读取网络数据的时候buffer handle出问题。应该是流量大的时候有些东西没有handle好。当然这一部分是可以继续改进的,加一些error handling和flow control的东西。
不过在这里我想说的意思是一个可以并发的client并不等于一个Load generator
Multi-thread client != Load Generator
因为load generator其实隐含了一个意思就是它自身不至于因为大的流量出问题,因为它是用来衡量别人的性能,如果自己出问题测试结果就没有意义了。而且一个实用的性能测试工具中,load generator做的事情除了产生流量外,还有一个很重要的工作就是记录响应数据,比如concurrent connection,response time,error rate等等,因为这些数据只有它最清楚。
一个好的load generator真的是要求很高的,自身就应该是高性能的,稳定的,可以扩展的网络应用程序。不是一个随便就可以写出的并发了流量的东西。大家在使用工具久了就会发现很多广为使用的性能测试工具也会自己出问题,我就遇到过测试工具crash或者memory leak的问题,比如JMeter,SilkPerformer还有Avalanche等测试设备。当然只是很偶然的发生,那么这个工具还是可用的了,但是如果像我上面写的这个这个脆弱的client,就难以担重任了。
好了,就写到这里吧。
Inspired by Kevin Y. during some coffee talk, and also thanks for his kindly help on Ruby!
by Ricky
Jan, 2010