Jmeter 摘抄
上一篇 / 下一篇 2007-10-28 21:02:13 / 个人分类:待分析
作为一个纯 JAVA 的GUI应用,JMeter对于CPU和内存的消耗还是很惊人的,所以当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至还会引起JAVA内存溢出的错误。不过,JMeter也可以像LoadRunner一样通过使用多台机器运行所谓的 Agent 来分担 Load Generator 自身的压力,并借此来获取更大的并发用户数。根据JMeter官方文档的署名,你需要自己完成这个配置,不过不用担心,这将非常简单 ^_^
1.在所有期望运行JMeter作为 Load Generator 的机器上安装JMeter,并确定其中一台机器作为 Controller,其他的机器作为 Agent。然后运行所有 Agent 机器上的JMeter-server.bat文件——假定我们使用两台机器 192.168.0.1 和 192.168.0.2 作为 Agent;
2.在Controller 机器的JMeter安装目录下找到 bin 目录,再找到JMeter.properties 这个文件,使用记事本或者其他文字编辑工具打开它;
3.在打开的文件中查找“remote_hosts=”这个字符串,你可以找到这样一行“remote_hosts=127.0.0.1”。其中的 127.0..0.1 表示运行JMeterAgent 的机器,这里需要修改为“remote_hosts=192.168.0.1:1099,192.168.0.2:1099”——其中的 1099为端口号。一般资料显示1644 为JMeter的 Controller 和 Agent 之间进行通讯的默认 RMI 端口号,但是我在测试的过程中发现设置为1644运行不成功。
在设置中还会出现一个问题,就是rmiregistry文件找不到,一般只要设置一下Java_home和JMeter_home就能成功,或者一个很野蛮的方法是可以直接将rmiregistry.exe放到%JMeter_home%bin下。
----
2.4.3 Non-GUI Mode (Command Line mode) |
|
----
ApacheJMeter(http://jakarta.apache.org/jmeter/)是来自 Apache Jakarta 项目的一个压力测试工具, 目前版本2.0.3,JMeter支持 HTTP, FTP, SOAP/XML-RPC, JDBC 等多种目标的压力测试(参见下图).
关于JMeter的一般使用在它的官方主页和其它网站可以搜索到不少文章, 但是很少看到如何使用一些动态内容(比如在 HTTP 请求中使用变量作为参数)的文章, 最近因为工作需要, 在这方面做了一些摸索, 总结如下.
0.测试项目概述
为了尝试如何使用变量, 我们首先需要建立一个测试项目, 在这里使用了 Buffalo (一种 AJAX 技术, 详细资料参见http://www.amowa.net/buffalo/index.html), 或者可以看一下我下载的这个文件(att:在JMeter压力测试工具中使用变量.Buffalo-info.zip)中的说明和例子. 目前 Buffalo 还不是很稳定, 但是建立一个测试环境已经足够了, 而且很方便.
我们建立的这个例子叫做 "buffalo-jmeter", 将这个压缩文件(att:在JMeter压力测试工具中使用变量.buffalo-jmeter.zip)中的buffalo-jmeter.war文件复制到 Tomcat(我用的是 Tomcat 5.0.30) 的 webapps 目录下, 待 Tomcat 自动发布完成之后就可以通过http://localhost:8080/buffalo-jmeter/(假设是发布在本地的Tomcat上) 访问测试页面(如下图).
在这个例子中我们假设一个业务: 首先通过 getToken() 获得一个凭证, 然后通过这个凭证使用 getOrder() 去申请一个订单, 凭证上存在时间记录, 如果超过设定的时间(例子中是10秒)后这个凭证就失效而无法用于申请订单了(在上图中的对话框正说明了这种情形).
1.测试中遇到的问题
首先我们需要知道 Buffalo 其实是一种 XML-RPC 技术, 所以我们可以使用JMeter的 SOAP/XML-RPC Request 这个 Sampler 进行测试, 但是为了方便快捷进行测试, 以下两个问题需要解决:
- 如果测试服务器发生变化, 如何方便的一次性改变所有请求的 URL 地址;
- 如上一节所述, 10秒钟后凭证会失效, 因此我们在测试 getOrder() 的时候不能输入固定的凭证号, 应该每10秒左右获取一个新的凭证, 这样操作的难点在于如何自动让JMeter得到新获得的凭证号并应用到 getOrder() 请求中.
2.静态变量(用户定义的变量)
JMeter允许对一个测试计划(*.jmx)设置用户定义的变量, 因此我们可以把象 URL 等需要统一修改的值作为变量定义起来(如下图);
变量在使用时可以使用 ${变量名} 的方式引用, 如下图:
3.从 Response 中获得数据
可以使用JMeter提供的 后置处理器(Post Processers) --> 正则表达式提取器 (Regular Expression Extractor) 从返回的结果中取得数据, 在确定 getToken() 请求的返回值是类似下列的 XML 之后,
<?xml version="1.0" encoding="utf-8"?> <burlap:reply xmlns:burlap="http://www.amowa.net/burlap/"> <string>TK1119466440468</string> </burlap:reply>
我们可以使用正则表达式 "<string>(.*)<\/string>" 来提取我们需要的凭证号.
首先我们可以使用Javascrīpt 正则表达式测试页面来测试一下这个正则表达式是如何被执行的(如下图):
可以看到执行结果中, 我们需要的凭证号处于"array[1]"的位置.
这样使用"正则表达式提取器"(如下图), 注意图中的"引用名称"就可以认为是存放提取出来的数据的变量名:
提取出来的变量可以这样被引用(如下图), 其中"_g1"代表"group number"(参见JMeter的联机帮助: ... [refname]_g# ... ... and # is the group number, where group 0 is the entire match, group 1 is the match from the first set of parentheses, etc.)
4.测试结果分析
我们使用3个线程同时对测试项目进行压力测试(如下图)
通过对结果的分析我们看到了提取出来的变量确实在起作用, 而且, 这个变量是每个线程各自独立的(如下图)
后记
- 对原 Buffalo 代码的修改:
- 原来
net.buffalo.server.BuffaloServiceServlet
中在输出结果 xml 中没有使用response.setContentType("text/xml")
, 这导致返回的 xml 没有正确的ContentType, 进而使JMeter无法获得 Response, 在代码中加上这句语句才能正确使用JMeter进行测试; - 下载的文件att:在JMeter压力测试工具中使用变量.buffalo-jmeter.zip中的
net.buffalo.server.BuffaloServiceServlet
是已经修改过这个问题的, 因此可以直接用于测试;
- 原来
- 文件att:在JMeter压力测试工具中使用变量.buffalo-jmeter.zip中还包括了上述的JMeter测试计划(Buffalo-test.jmx).
在 JMeter 压力测试工具中使用函数(Function)
在文章在JMeter 压力测试工具中使用变量中谈到了可以在JMeter 中使用变量来方便进行压力测试, 此外, JMeter 还支持在测试计划中使用函数, 下图是 JMeter 提供的"函数助手对话框":
通过"函数助手对话框"中的"帮助"按钮可以查找到相关函数的帮助.
实现方式
下面使用一个例子来说明如何使用函数, 如下面的几张图所示, 例子使用了 JMeter 提供的 "Java请求" 这个 Sampler.
- <1>这里设置了一个 Label "JavaTest001", 以便在运行结果中区分当前请求
- <2>
${_ _javascrīpt((new Date()).getTime(),timestamp)}
就是 JMeter 中使用函数 "_ _javascrīpt" 的方法 - <3>这里演示了如何使用上一条中 "_ _javascrīpt" 函数中产生的结果 "timestamp"
- <4>这里使用了另外一个 JMeter 函数 "_ _threadNum", 用以获得运行是线程编号
- <1>这里设置了一个 Label "JavaTest002", 以便与"Java请求01"中的运行结果分开
- <2>这里演示了如何再次使用"Java请求01"中 "_ _javascrīpt" 函数中产生的结果 "timestamp"
结果分析
- 从这个结果可以看到 "_ _javascrīpt" 函数的测试结果, 以及如何使用这个函数执行时产生的结果 "timestamp"(=1120144567828)
- 从这个结果中可以看到另外一个函数 "_ _threadNum" 的使用效果
- 从这个结果中可以看到在"Java请求01"中 "_ _javascrīpt" 函数中产生的结果 "timestamp" 是如何被引用在"Java请求02" 中的
其它
- 与本文相关的 JMeter 测试计划文件 "JMeter-func.jmx" 可以从这里下载:att:在JMeter 压力测试工具中使用函数(Function).JMeter-func.jmx
-----
在 LR 中是有一个“网页细分图”的,通过这个图,你可以比较容易的区分哪些请求的响应时间最长,如果响应时间过程,是消耗在server处理的时候,还是消耗在网络传输过程中——也就是所谓的 Server time 和 Network time。
JMeter并没有提供这么详细的区分——至少目前尚未发现,但是在JMeter的执行结果中也有一个字段可以利用一下。如果想看到这一项,首先要设置将JMeter运行结果保存到 XML 格式。
在JMeter.properties 中找到
JMeter.save.saveservice.output_format=csv 改为
JMeter.save.saveservice.output_format=xml
重新启动JMeter,执行一个脚本并保存测试结果。
使用任何一个文本编辑工具打开 .jtl 文件,内容如下:
2 <testResults version="1.2">
3 <httpSample t="2969" lt="1906" ts="1159349557390" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" ng="5" na="5"/>
4 <httpSample t="2797" lt="1719" ts="1159349557609" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-2" dt="text" ng="5" na="5"/>
5 <httpSample t="2625" lt="1594" ts="1159349558015" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-4" dt="text" ng="5" na="5"/>
6 <httpSample t="2843" lt="1812" ts="1159349557812" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-3" dt="text" ng="5" na="5"/>
7 <httpSample t="2687" lt="1110" ts="1159349558218" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-5" dt="text" ng="5" na="5"/>
8 <httpSample t="844" lt="391" ts="1159349560374" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" ng="5" na="5"/>
9 <httpSample t="843" lt="437" ts="1159349560406" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-2" dt="text" ng="4" na="4"/>
10 <httpSample t="781" lt="422" ts="1159349560640" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-4" dt="text" ng="3" na="3"/>
11 <httpSample t="782" lt="391" ts="1159349560905" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-5" dt="text" ng="2" na="2"/>
12 <httpSample t="1188" lt="485" ts="1159349560655" s="true" lb="http://jackei.cnblogs.com/" rc="200" rm="OK" tn="Thread Group 1-3" dt="text" ng="1" na="1"/>
13
14 </testResults>
15
找到 lt 这一项。
结合JMeter的几篇文章和 email,解释一下 lt 的意思。
lt =latency time (ms)
在JMeter中执行一个脚本时,大概的过程如下:
Start timer
Send Request
Wait for data
Initial (first) response packet occurs - this is latency
more data
...
end of response
Stop timer - this is the response time
这里可以看到 lt 是接收到响应的第一个包的时间。
而上面的 XML 文件中,t 这一项表示的是 elapsed time。也就是一个请求从发出到收到完整的响应的时间。
那么 lt 就相当于 LR 中的 Server time,而 t-lt 就相当于 LR 中的 Netwrok time。
相关阅读:
- 调ws的一些方法(未消化的)~ (Wins, 2007-8-04)
- 学会LR不等于学会性能测试 (Wins, 2007-8-07)
- stubtest_jetty (Wins, 2007-9-05)
- 批量修改配置文件 (Wins, 2007-10-19)
- apache 性能调优-2.2版中文手册(转) (Wins, 2007-10-28)
TAG: 待分析
标题搜索
日历
|
|||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
1 | 2 | 3 | 4 | 5 | 6 | ||||
7 | 8 | 9 | 10 | 11 | 12 | 13 | |||
14 | 15 | 16 | 17 | 18 | 19 | 20 | |||
21 | 22 | 23 | 24 | 25 | 26 | 27 | |||
28 | 29 | 30 |
我的存档
数据统计
- 访问量: 59681
- 日志数: 56
- 建立时间: 2007-07-31
- 更新时间: 2012-12-18