有近一年没有写博客笔记了,现在又重新拾起。
最近又开始做性能测试,场景是模拟终端设备给服务器发心跳,协议是底层的TCP协议。因为最近一年偶尔做下性能测试也都是基于http协议,所以在工具脚本选择上有很大的空间,C语言系的LoadRunne、Java系的Jmeter、Python系的Locust等等。。 基于底层TCP自定义协议的场景只在一年前使用LoadRunner的winsocket协议实现过一次,不过也都快忘的差不多了,还好之前都有记录,所以稍复习下,捡起来也比较快。
因为已经有现成的jmeter脚本了,所以考虑先调试通jmeter脚本就可以压测了。相对另外两款工具,jmeter算是不那么熟悉的,mac上下载安装了最新的jmeter3.2版本,打开现成的脚本后发现缺少BFS前置处理器,刚好脚本里又有用到,纳闷了。。。 于是猜测可能是版本跟原来弄这脚本时的版本不一致,于是下载安装较低的版本,3.1版本、3.0版本,果然在3.0版本中就有BSF前置处理器了,而且括号中提示不建议使用,原来是早就可能打算要丢弃的功能。
为什么需要jmeter中的BSF前置处理器,主要就是做数据的中间处理,jmeter默认发送的数据是文本的,而实际需要的是最终发送的是按协议定义格式的二进制数据,而且需要将参数化的文本数据经过转换得来。那BSF又是什么呢?稍查了下:Bean Scripting Framework (BSF) is a set of Java classes which provides scripting language support within Java applications, and access to Java objects and methods from scripting languages. 就是java的一个项目,实现在java应用程序中支持各种脚本语言访问java对象和方法,脚本语言包括:jython、javascript、perl、tcl等等,而当前脚本中使用到的是jython。于是使用jmeter3.0版本进行调试,单用户运行下报异常了,提示无法加载jython语言,由于时间紧就直接询问了之前弄脚本的测试老大,需要在jmeter中增加jython的jar包,下载jython.jar包置于jmeter安装目录下,再次运行就正常跑通了。
看来要使用jmeter的BSF前置处理器功能的话,需要自行添加对应语言环境的jar包到jmeter中方可识别。不过另一个问题来了,看起来这个功能很不错哦,可以在jmeter中使用自己熟悉的语言做些数据处理之类的前置后置处理工作,jmeter最新版本中为啥又去掉了这个功能呢?去掉的原因暂时还未查到,那总得知道最新的替代方案吧,稍微查了下,类似的处理可以使用BeanShell前置后置处理器来做。BeanShell是啥,java源码解释器,就是能动态执行JAVA源代码并为其扩展了脚本语言的一些特性。 由此要使用最新版本解决此类问题,就得去熟悉下BeanShell了。
与之前使用LR做性能测试相比,觉得jmeter真没那么好用,由于是开源的东西,操作体验不易用、琐碎、bug多、报告弱、只提供界面操作不支持单独写业务代码总觉得没那么可靠。。 也是最不喜欢的一点,脚本支持能力太弱,而且据说jmeter依靠java的多线程实现并发,资源消耗也是比较高的。就不吐槽了,毕竟开源不要money,最大的优势是可以修改工具源码进行二次开发。继续正题,一直以来都只是做单机的压测,不需要考虑负载均衡,不过我们的服务端环境最近增加了负载均衡,将来自终端的前端压力分散到两台不同的服务器主机上,对于压力测试来说有什么不一样么?有的,就是现在需要前端过来的压力的客户端IP地址不一样,负载均衡使用的是IP HASH做的均衡策略,就是来自同一个IP地址的客户端压力会分到同一台后端主机上,因此要测试负载均衡的功能,就需要模拟不同的客户端IP,这也算是软件测试中要尽可能真实的模拟实际场景的体现了。只知道LR中有IP欺诈的功能可以实现,jmeter中能否实现呢?
网上查了下,关于jmeter的ip欺诈,基本都是在说http协议,http的取样器中有个可以参数化源ip的地方,先在测试压力机上配置多个不同的可用ip,并保证与服务器的互通,然后jmeter脚本中在http取样器的源IP的地方参数化之即可实现,另外,jmeter的分布式测试,直接利用不同的节点本身不同的ip地址,可算是可以实现少量几个不同的客户端IP了,不过这说的都是http,tcp的取样器中是找不到可以配置源IP的地方的,莫非对于tcp协议压根就不支持呢,遂又看了下jmeter的官方文档,果然有说到ip spoofing功能只支持http的取样器。看来要实现tcp协议的ip欺诈,直接的方式jmeter是做不到了(不排除有我暂时还不知道的方法)。。。
打算使用LR来实现这个需要IP欺诈的压测脚本了,弄了台win8的机器,安装了LR11并进行了破解。使用winsocket协议提供的API实现脚本,调试,基本就都是C语言的一些偏底层的东西了,API、二进制、十六进制、字节、内存、字符串处理、编码、数据格式转换、tcp/ip协议。。。调试通过后进行LR的场景设置、包括ip欺诈的设置、启动压测调试,为了确认ip欺诈功能生效,脚本中已经添加了打印vuser虚拟用户的ip的脚本,另外从LR的contraller Vuser运行日志中也能查看使用的ip地址,日志中IP地址确实使用了不同的IP,满以为IP欺诈功能正常生效了,却发现服务端日志中收到的客户端都是同一个IP,这里还有个小曲折,因为客户端压力机到服务器的中间具体组网不是很清楚(公司里有专门的运维负责这一块),不过从运维那里了解到,理论上如果脚本中是通过域名来访问的话,即使使用了IP欺诈功能最后服务器主机收到的也还是同一个ip,因为在域名转换为ip地址的过程中,最终服务器收到的包的源IP都是中间转换机器的源IP,而不再是原来客户端的ip了,因此脚本的访问地址需要直接使用负载均衡机器的IP地址,最后的服务器主机收到的包的源IP才会是客户端的IP。
不过即使是脚本使用了正确的方式,服务器主机收到的IP还是只有一个IP(网卡上配置的多个IP后的第1个IP),通过在客户端抓包查看,脚本发出的包的源IP确实都是同一个IP,虽然日志中是不同的IP,又纳闷了。。。难道是破解的LR不提供ip欺诈功能么?反正不是正版的话都值得怀疑,再次网上查了下,有人也遇到过同样的问题,原来是受限于操作系统,LoadRunner11及更早的版本的IP欺骗可以在XP或者Windows Server2008的机器上使用,在win7、win8上是不生效的,无论怎么配置,从LoadRunner上显示的是IP欺骗功能使用正常,但抓到的IP包永远都是某个固定IP。。。 没办法盗版就这支持程度,实在不想再重装个操作系统来折腾这事了,主要还因为一个原因是,LR的winsocket协议只能在微软的windows机器上跑,而后续我们还需要压测更大的并发,需要利用服务器来做压力机,而空闲的服务器都是linux的系统,如果使用LR的windsocket脚本的话也是用不了的(http协议的话是可以的),所以暂时还是用jmeter脚本跑在两个不同的机器上,同时进行启动压力测试,确认下负载均衡是否生效、相比单机的性能情况了。
有没有更好的解决支持自定义的tcp协议同时支持IP欺诈功能进行压力测试好的方案呢,购买正版LR就不说了,不是大公司使用LR成本还是太高了,能破解用下就用下,不能的话还是老老实实考虑开源的方案。Jmeter的tcp协议取样器是不支持的,如何进行扩展开发来支持ip欺诈?Locust使用python比较容易扩展,本身自带的客户端是http的,不过官网给出了利用python模块来扩展其他协议的客户端实例,大概写了下demo,扩展实现支持tcp的客户端基本是可以实现的,不过如何扩展来实现支持ip欺诈功能?有没有其他好的工具来解决呢,有同事推荐使用tsung框架,基于erlang语言。。。
在此记录下性能测试实现过程中遇到的这些坑。