本文发表于《程序员》杂志2013年

1,服务器性能测试工具简介

服务器性能测试主要是以测试服务器的性能为主的测试方法,通过模拟多用户按照预定义好的规则对服务器进行并行访问,监测并记录服务器的Response Time,Throughput, Server Hits 以及Memory和CPU等实时数据,通过分析测试数据,得到服务器的各项性能指标从而发现服务器的性能瓶颈和内存泄漏等问题。进行这样测试的工具称之为服务器性能测试工具。

服务器性能测试工具通过多年的发展,已经从ab/abs这种简单的命令行工具发展到有丰富UI配置界面的Jmeter,LoadRunner,到现在的Gatling支持DSL/Actor, LoadUI支持图形化网络接口的新一代工具, 可以说是种类繁多。对于各种不同的需求,应该都能找到一款相对合适的工具。如果只是想做入门级别的压力测试,比如只是需要简单的产生许多HTTP请求,那么ab 和curl-loader就能完成工作;如果需要在有限的设备上进行最大强度的发包,那么Gatling和 Locust将是不二选择;如果资金充裕,商用的LoadRunner和LoadUI Pro绝对能满足需求;如果你是Windows的忠实拥护者,那么OpenSTA和WebLoad也是很好的选择;如果你并不是喜欢编程和修改xml,并且资金也不充裕,那么Jmeter和LoadUI是不错的选项;如果你是Python爱好者,那么Locust和Grinder 将可以延续你的爱好。

总之,每个工具都有自己的优点和缺点,只要根据需求以及资金情况选择合适的工具就可以了。因为每个工具的基本功能都是产生尽可能多的网络请求,然后收集各种数据并展现出来。只不过由于使用的技术不同以及开发者的目标不同,所以得到的效果不一样而已(详见第二节 )。

2,主要的服务器性能测试工具

对于现在已有的服务器性能测试工具如果按照表现模式,主要可以分为命令模式,图形模式,脚本模式。下面就对一些主要的工具进行一下介绍。

命令模式:

  • ab/abs: ab/abs是Apache Http Server自带的一款的性能测试工具,安装了Apache就可以在其目录下面找到它。它具有体积小,性能高的特点,缺点是没有界面,报表简单,很难使用其进行复杂流程的性能测试,必须借助第三方语言的帮助,比如Bash Shell,Python 等。

  • curl-loader:curl-loader 是一款基于c开发的命令行工具,拥有和ab/abs一样的特点,但是支持更多的功能,比如FTP 和TLS/SSL协议栈,支持用户认证和登陆,拥有更好的报表系统。所以如果想要一个功能加强版的ab/abs,那就选择curl-loader。

图形模式:

  • LoadUI:LoadUI是一款开源免费的性能测试工具。它除了拥有和其他性能测试工具一样的功能以外,还具有一个很有创意的特性:图形化网络接口,即拖即放即使用。这个特性使得可以通过拖放网络接口组件来组成的网络拓扑图,然后基于这个拓扑图进行性能测试,以及检查和观察测试情况。它基本上支持所有标准协议,比如HTTP(S), HTML, SOAP/WSDL 和 REST to AMF, JDBC, and POX。作为入门级别的测试工具或者练习,它绝对是一款很不错的工具。

  • LoadUI Pro:LoadUI Pro是基于LoadUI增强功能的收费版,其更为强大的功能绝对物超所值,详细比较请见(http://www.loadui.org/About-loadUI/compare-loadui-and-loadui-pro.html)。虽然LoadUI价格也不便宜,但是和LoadRunner比就便宜很多了。

  • LoadRunner:LoadRunner可以算业界最出名,也是功能最为强大的服务器性能测试工具,当然价格也十分昂贵。它是2006年HP从Mercury Interactive购买过来的产品。它可以模拟各种性能测试行为,支持的协议也十分众多,比如Flex AMF, Citrix ICA, Remote Desktop Protocol (RDP), ERP/CRM (e.g. SAP, Oracle eBusiness, Siebel and PeopleSoft), Databases, Mail Clients, Web Services等。如果资金充裕,选择它应该能满足绝大部分需求,不过其性价比确实是一个不大不小的问题。

  • Apache Jmeter:Apache Jmeter是现在最流行的免费服务器性能测试工具之一。它是一个100%纯java开发的应用程序,其图形界面的易用性可以和LoadRunner相提并论,其丰富的插件提供了各种协议的支持,丰富的测试报表,扩展组件BSF支持各种语言的扩展,比如JavaScrip,Ruby,Python等,以及支持分布式等各种先进的特性。当然Jmeter也不是完美的,它也存在一些不足。不过对于服务器性能测试入门以及没有很好的技术储备并且资金不充裕的公司来讲,Jmeter将是一个完美的选择。

脚本模式:

  • Tsung:Tsung是一款基于Erlang开发的高性能免费的服务器性能测试工具,它具有分布式,录制脚本,图形报表系统等功能,协议方面支持HTTP,SOAP,和Jabber Server(SSL)等。其测试脚本是通过XML来进行描述的。由于没有图形管理界面,所以编写和维护测试脚本将会是一个不小的困难。如果要对其进行扩展,也需要通过Erlang。除非公司有Erlang的技术人员,不然就不要轻易选择其作为主要的测试工具。

  • Grinder:Grinder是一个基于Java开发,通过Jython(最新版增加了Clojure的支持)驱动的Load-Testing 框架。由于可以通过编写Jython脚本来实现测试案例,从而获得了一些喜欢Python的技术人员的喜爱。不过由于Jython本身的一些问题,也造成了Grinder会出现内存泄漏,不稳定等情况。所以对于小规模性能测试并且拥有很好的Python技术人员储备的公司,还是可以选择Grinder进行尝试。

  • Locust: Locust是一个基于Python开发,并且通过编写ython脚本来实现测试场景。它通过异步事件模型达可以实现高并发请求,同时它还支持分布式模型,从而可以扩展并实现超高并发请求。如果性能有很高的要求,并且拥有很好的Python技术人员,可以选择Locust进行性能测试。

  • Gatling:Gatling是最近才出现的新一代服务器性能测试工具,它具有高性能,轻量表报,以及DSL脚本的特性。如果想要获得和Tsung一样或者更好的性能,如果希望支持简单易读的DSL脚本并且希望能在IntelliJ有插件的支持,如果想要轻量报表系统,那么Gatling是唯一选择。

如果资金充裕, 购买商用的测试工具是很好的选择,但是如果只是一个创业公司或者并不想在服务器性能测试工具上做太多的投资,那么第三节的内容也许能提供一些帮助。

3,三个真实项目中性能测试工具实战

1, 在一个 Erlang 开发的电信计费系统中从Tsung转向Jmeter

我曾参加过一个电信计费系统项目的测试工作,这个项目始于90年代,那个时候Java刚刚起步,对于并发性能和容错要求十分严格的电信系统来讲,Erlang几乎是唯一选择。但是由于公司规模较小,所以也没有太多的预算去购买商用的性能测试工具, 所以只是简单的将单元测试改装一下进行并发调用(比如调用一个函数1万次)来做性能测试。这样的目的仅仅只是检查函数被并发调用的时候会不会出现一些问题,而无法测试真实的场景。进行到项目中期的时候,我们发现这样的测试其实并不能发现一些场景中的性能问题,所以开始寻找一个工具可以基于场景非单元而进行性能测试。由于项目的开发人员都十分熟悉Erlang,也是基于Erlang优秀的并发性,所以选择了用Erlang开发的Tsung。虽然Tsung支持录制功能,由于它的测试脚步都是基于XML,修改也需要直接修改XML,所以在使用过程中发现对于流程比较复杂的测试案例,并且流程需要变化的时候对测试脚本的开发和维护十分麻烦。在Debug测试脚本的时候无法动态显示报表而只能看日志,所以最终我们决定抛弃Tsung而使用Jmeter。

选用Jmeter主要是基于其开发和维护的大部分工作只需要在界面上对Test Plan进行配置,然后可以通过BSF进行少量的脚本开发就能开发复杂的测试案例。我们的具体开发流程是首先通过界面配置并发线程的规则以及主要的测试流程,然后对于某些有特殊要求的测试案例编写Ruby脚本并封装在BSF Sampler中,比如对结果进行特定分析,处理然后存储到数据库或者文件等特殊需求。由于BSF支持几乎所有可以在JVM上运行的语言,比如Jython,JRuby,Javascript等,所以可以选择熟悉的语言编写这种特殊需求的测试扩展。

当然Jmeter也不是完美的,因为使用过程中我们也遇到一些问题:

  • 通过界面方式运行Test Plan的时候,如果线程过多,比如超过1000-2000个线程(在我们项目特定的硬件环境下),那么界面以及Listener里面的图表会出现死屏的情况。所以开发和调试的时候需要把线程设置到1000以下最好,或者通过命令行无界面的方式进行测试。

  • 由于Jmeter是基于Java Thread的模型开发的,并没有Tsung这种基于Actor模型的效率高,所以我们选用了Cluster的模型进行测试。但是发现当Node过多,从Node传向Server的数据也会跟Node的个数成线性增长,但是能达到的并发请求却不能成等比线性增长,要低于理论值很多,所以对硬件资源的浪费也是比较大的。

  • 如果设置的线程太多,很容易出现OOM,所以我们一般最高单机设置不会超过2000个Thread对于简单的测试案例。

  • 如果进行Soak Testing 超过1天,并且Result采用XML的格式存储,其结果文件大小会达到几个G甚至10多个G。如果Result改为CSV格式存储,其大小也有几百兆,如果Testing超过1周,那么数据也是巨大的。打开这个巨大的Result文件查看各种Listener图表需要很长时间,是一件十分痛苦的事情,如果太大还会出现OOM。

2, 在一个 J2EE 开发的Social Network项目中从Grinder转向Jmeter

21世纪开始的10年是属于社交网络的10年,全世界的社交网络如雨后春笋般一下子都涌现出来。我们公司也是其中一笋,开发了一款社交网络系统。对于社交网络系统,其并发性能和容错的要求一点也不亚于电信计费系统。由于开发此系统的时候正是脚本开发时代,所以系统的架构师选择了基于Python开发的Grinder来做性能测试。由于Grinder需要编写Jython脚本,并且由于项目开发进度的问题,只是开发了基本场景的Performance Testing, Load Testing,Soak Testing。基于这些场景我们开始寻找系统的处理极限,是否存在内存泄漏等问题,根本没有时间去做比较复杂测试 。在做Soak Testing的时候我们还证实了Grinder存在的内存泄漏问题,最终这一切不得不使我们抛弃了Grinder而选择Jmeter。

在这个项目里面我们尝试了去通过将Server部署在VM Node上,从而使其在低配置的硬件设备上运行。这样通过Jmeter就不需要产生大规模的并发请求,就可以比较容易的达到Server的访问极限,从而规避Jmeter的性能问题。当然这种方法并不是一种完美的解决方案,也存在其问题,比如无法真实模拟现实情况。但是由于部署和产品环境一样的硬件进行测试,本身硬件成本就十分的高。利用这种方案,不仅减少了公司对测试环境的硬件投入,还减少了一定软件成本,比如配置和维护Jmeter Cluster。最后通过CI进行测试时候,也减少了CI的配置和维护成本。

3, 在一个开发的 J2EE 的商业系统中尝试使用新一代工具Gatling

最近正在开发一个基于J2EE的商业系统,其业务逻辑比较复杂, 但是对并发性能要求并不十分高,所以从项目开始就选择了Jmeter作为服务器性能测试工具。我们基于Jmeter开发了各个场景下的Test Plan,并通过Jenkins进行测试。由于测试场景比较复杂,所以Test Plan里面的Sampler, Assertion 等也很多,运行时占用的内存也比较多,数据交互也比较多,存储的Result也比较大。鉴于我们之前项目的经验,Jmeter并不适合做这样项目的Soak Testing。

幸运的是Gatling的出现刚好能解决这样的问题。Gatling是基于Scala和Akka开发的新一代服务器性能测试工具,它使用的Actor 和异步IO使其在并发性能方面远远超越了Jmeter,它的报表系统是HTML文件来存储的并配有丰富的动态图表,所以它的高性能和轻量报表系统刚好弥补了Jmeter在Soak Testing和单机高性能方面不足的问题。

Gatling还具有以下特性:

  • 支持DSL,使得测试脚本更为简明和更好的可读性

  • 支持轻量和动态页面的HTML测试报表

  • 支持录制并直接生成测试脚本

  • 支持Maven插件,可以很好的和Eclipse/IntelliJ等IDE进行集成

  • 支持Jenkins插件

  • 支持Debian Package,所以带Debian和Ubuntu下面可以通过apt-get进行快速安装和使用

现在我已经开始考虑尝试用Gatling重写一部分测试案例来进行Soak Testing,从而将项目带入Gatling时代。

Gatling也不是完美的,它发布的时间也不长,当然也存在一些不足,详见下节。

4,服务器性能测试工具的发展和设想

虽然现在已有的各种免费服务器性能测试工具已经拥有了十分丰富的功能,但是仍有一些需要改进和加强的地方。

更为强大的Server Monitor: 虽然Jmeter的Plugin已经实现了Server Monitor,或者也可以通过第三方工具比如OpenTSDB进行Server Monitor,但是真正使用起来还是很不方便。比如在第二个实战项目中,我们就是自己通过Python脚本收集Server的JMX信息,然后传递给OpenTSDB,分析数据的时候需要根据时间轴分别查看Jmeter和OpenTSDB的图表。如果能把收集和显示JMX等这类Server系统内部信息的功能集成入测试工具,那么就可以在同一个报表系统里面查看Client端和Server系统内部各种信息,从而更简单的进行测试数据分析。

更好的CI支持:现在最流行的免费CI-Jenkins/Hudson虽然有插件支持Jmeter等工具,但是仅仅是显示一下汇总数据,并不能将各种报表和详细数据显示到CI上。如果CI上能直接显示甚至自定义各种数据报表以及实时显示数据报表,那么将可以极大的方便的日常测试工作,并加快测试分析和测试数据汇总。

Jmeter的未来:Jmeter对于不会写代码的测试人员就是一个天使,但是由于其性能和报表问题,往往不能在有限的设备上发挥硬件的最大能力。所以如果能用Actor替换掉Thread,让其能充分发挥硬件的性能,并且能有轻量级的报表系统,比如直接可以将Report存储成为HTML文件,那么Jmeter将会迎来另外一个春天。

Gatling的未来:Gatling是最新一代服务器性能测试工具,它不仅有出色的性能,而且而且还支持DSL和Scala脚本开发(Scala可以不需要编译而以脚本的方式执行)。但是它现在不支持分布式也算是它的一个不大不小的问题,所以如果未来Gatling支持分布式并支持更多种类的报表和协议,那么它很有可能在未来的免费服务器性能测试工具市场上占据主导地位。

总的说来,现在已有的服务器性能测试工具基本上都能满足基本的业务需求,只不过根据自己的技术能力和业务需己选择适合自己的就可以了。最后还是给出我个人的推荐,对于HTTP服务器:免费-Gatling, Locust;收费-LoadUI Pro。