最近需要对改造的redis缓存接口做压力测试,使用了开源压力测试工具JMeter,分享一下自己的使用经验,希望能对需要进行压力测试的开发同学有所帮助。

JMeter介绍

JMeter是Apache软件基金会下的一款开源压力测试工具,官方网址是:http://jmeter.apache.org/。JMeter可以测试静态、动态资源的性能,这些资源包括文件、Servlets 、Perl脚本、Java对象、数据库、FTP服务器等,并生成图形报告。JMeter使用Java开发,既支持可视化界面操作,也支持命令行操作。

Java请求测试(界面操作)

由于需要对改造的redis缓存接口测试,因此使用了JMeter的Java请求测试,安装和使用步骤如下所示(以Windows操作系统为例,并默认已安装、配置Java运行环境)。

1)从官网上下载JMeter并解压,例如解压至C:\apache-jmeter-2.9。

2)配置JMeter环境变量,增加变量JMETER_HOME,值为“C:\apache-jmeter-2.9”,修改变量CLASSPATH,增加“%JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;% JMETER_HOME%\lib\jorphan.jar;%JMETER_HOME%\lib\logkit-1.2.jar;”

3)执行JMeter目录下的bin\jmeter.bat,显示JMeter界面说明安装成功。

4)新建Java工程,在该工程中,引入JMeter目录下lib中的jar包,继承JMeter的AbstractJavaSamplerClient类,在子类中重写setupTest、teardownTest、getDefaultParameters、runTest方法,实现对缓存接口的get、set、hGet、hSet方法进行测试,子类代码如下所示。

package com.sohu.cms.test;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sohu.cms.datacache.DataCache;
import com.sohu.cms.datacache.DataCacheManager;
/**
* 继承jmeter的AbstractJavaSamplerClient类,
* 重写setupTest、teardownTest、getDefaultParameters、runTest方法
* 对缓存接口的get、set、hGet、hSet方法进行测试
* @author wang
*
*/
public class TestDataCacheClient extends AbstractJavaSamplerClient{
private static long start = 0;
private static long end = 0;

private static DataCacheManager dataCacheManager;
private static DataCache dataCache;
private static int size = 8192;
private static String method = "get";
private static Object key = "TEST_KEY";
private static Object field = "TEST_FIELD";
private static Object value = new Byte[size];

//此处初始化我们改造的redis缓存接口dataCache
static {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
dataCacheManager = (DataCacheManager) context.getBean("dataCacheManager");
dataCache = dataCacheManager.getObjectDataCache();
}
/**
* 测试开始
*/
public void setupTest(JavaSamplerContext arg0) {
start = System.currentTimeMillis();
}
/**
* 测试结束
*/
public void teardownTest(JavaSamplerContext arg0) {
end = System.currentTimeMillis();
System.out.println("[method=" + method + "] [size=" + size + "] [time:" + (end - start) / 1000);
}
/**
* 添加参数默认值,参数默认值会在界面中显示
*/
public Arguments getDefaultParameters() {
//添加两个参数,
//size为测试value值的字节大小,默认为8192字节
//method为需要进行测试的缓存接口方法,默认为get
Arguments args = new Arguments();
args.addArgument("size", "8192");
args.addArgument("method","get");
return args;
}
/**
* 测试
*/
public SampleResult runTest(JavaSamplerContext arg0) {
//获取界面或测试计划配置文件(jmx)中传入的参数
if (arg0.getParameter("method") != null) method = arg0.getParameter("method");
if (arg0.getIntParameter("size") > 0) size = arg0.getIntParameter("size");
value = new Byte[size];

SampleResult sr = new SampleResult();
try {
boolean result = true;
//根据传入的method参数测试相应的缓存接口方法
if (method.equals("get")){
//测试用例的核心逻辑
//测试用例开始
sr.sampleStart();
//测试用例执行
result = get();
//测试用例结果
sr.setSuccessful(result);
//测试用例结束
sr.sampleEnd();
} else if (method.equals("set")) {
sr.sampleStart();
result = set();
sr.setSuccessful(result);
sr.sampleEnd();
} else if (method.equals("hGet")) {
sr.sampleStart();
result = hGet();
sr.setSuccessful(result);
sr.sampleEnd();
} else if (method.equals("hSet")) {
sr.sampleStart();
result = hSet();
sr.setSuccessful(result);
sr.sampleEnd();
}
} catch (Exception e) {
e.printStackTrace();
}
return sr;
}

/**
* 缓存接口get方法测试用例
* @return
*/
public boolean get() {
boolean result = true;
try {
dataCache.get(key);
} catch (Exception e) {
System.out.println(e);
result = false;
}
return result;
}

/**
* 缓存接口set方法测试用例
* @return
*/
public boolean set() {
boolean result = true;
try {
dataCache.put(key, value);
} catch (Exception e) {
System.out.println(e);
result = false;
}
return result;
}

/**
* 缓存接口hGet方法测试用例
* @return
*/
public boolean hGet() {
boolean result = true;
try {
dataCache.hGet(key, field);
} catch (Exception e) {
System.out.println(e);
result = false;
}
return result;
}

/**
* 缓存接口hSet方法测试用例
* @return
*/
public boolean hSet() {
boolean result = true;
try {
result = dataCache.hSet(key, field, value);
} catch (Exception e) {
System.out.println(e);
result = false;
}
return result;
}
}

5)将工程以jar包形式导出,置于JMeter目录lib\ext下,并将工程依赖的jar包置于JMeter目录lib下,启动JMeter。右键“测试计划”添加“线程组”。右键“线程组”添加“Java请求”,右键“Java请求”添加“聚合报告”。

6)在“Java请求”中选择所写的测试类,并可以设置相关参数,在“线程组”中可以设置并发线程数和循环次数,点击上方“启动”按钮开始测试,测试完成后,可以在“聚合报告”中查看到测试结果。

Java请求测试(命令行操作)

JMeter也支持命令行操作,在服务器上进行测试时,我们就采用了这种方式。一个简单的JMeter命令行操作如下所示(在JMeter目录bin下执行)。

Windows下: JMeter-n –t test.jmx -l result.jtl

Linux下: ./jmeter.sh -n –t test.jmx -l result.jtl

其中-n 表示命令行执行,test.jmx为测试计划配置文件,result.jtl为测试结果。

可在界面中进行测试计划配置,然后保存便可生成jmx格式文件,如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.4" jmeter="2.9 r1437961">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="测试计划" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="线程组" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<!-- 循环次数 -->
<stringProp name="LoopController.loops">100</stringProp>
</elementProp>
<!-- 并发线程数 -->
<stringProp name="ThreadGroup.num_threads">100</stringProp>
<stringProp name="ThreadGroup.ramp_time">100</stringProp>
<longProp name="ThreadGroup.start_time">1376103961000</longProp>
<longProp name="ThreadGroup.end_time">1376103961000</longProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<JavaSampler guiclass="JavaTestSamplerGui" testclass="JavaSampler" testname="Java请求" enabled="true">
<elementProp name="arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" enabled="true">
<!-- 自定义参数 -->
<collectionProp name="Arguments.arguments">
<elementProp name="size" elementType="Argument">
<stringProp name="Argument.name">size</stringProp>
<stringProp name="Argument.value">8192</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="method" elementType="Argument">
<stringProp name="Argument.name">method</stringProp>
<stringProp name="Argument.value">set</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.sohu.cms.test.TestDataCacheClient</stringProp>
</JavaSampler>
<hashTree>
<ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="聚合报告" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>

result.ftl为按行输出的测试执行结果,如下所示,可在界面操作的聚合报告导入该文件从而生成聚合报告。

...

1376040889436,48,Java请求,,,线程组1-40,,true,0,0

1376040889792,9,Java请求,,,线程组1-7,,true,0,0

1376040889526,167,Java请求,,,线程组1-57,,true,0,0

1376040889791,10,Java请求,,,线程组 1-54,,true,0,0

...

JMeter使用jar进行压力测试的更多相关文章

  1. JMeter (3) —— JMeter录制脚本并压力测试用户登陆场景以CAS SSO为例(101 Tutorial)

    JMeter (3) -- JMeter录制脚本并压力测试用户登陆场景以CAS SSO为例(101 Tutorial) 主要内容 JMeter录制脚本并进行压力测试用户登陆场景,并以CAS SSO单点 ...

  2. 【转】使用JMeter 完成常用的压力测试(三)

    使用JMeter 完成常用的压力测试 发布时间: 2008-9-27 15:33    作者: 未知    来源: 网络转载 字体:  小  中  大  | 上一篇 下一篇 | 打印  | 我要投稿 ...

  3. Jmeter教程 简单的压力测试

    Jmeter教程 简单的压力测试:http://www.cnblogs.com/TankXiao/p/4059378.html

  4. 转:使用 JMeter 完成常用的压力测试

    使用 JMeter 完成常用的压力测试 就目前 Java EE 的平台下开发的软件来说,这种节点通常可能是:Web 服务器.数据库服务器和 JMS 服务器.它们都是请求主要发生的地点,请求频率较其它的 ...

  5. Windows和Linux的Jmeter分布式集群压力测试

    Windows的Jmeter分布式集群压力测试 原文:https://blog.csdn.net/cyjs1988/article/details/80267475 在使用Jmeter进行性能测试时, ...

  6. 【转】使用JMeter 完成常用的压力测试(二)

    使用JMeter 完成常用的压力测试 Login.jsp 和welcome.jsp.其中 login.jsp 负责生成 User 对象,并调用 User 的login.当 login 返回为 true ...

  7. 学习总结——JMeter做http接口压力测试

    JMeter做http接口压力测试 测前准备 用JMeter做接口的压测非常方便,在压测之前我们需要考虑这几个方面: 场景设定 场景分单场景和混合场景.针对一个接口做压力测试就是单场景,针对一个流程做 ...

  8. Jmeter教程 简单的压力测试【转】

    Jmeter教程 简单的压力测试[转] Jmeter是一个非常好用的压力测试工具.  Jmeter用来做轻量级的压力测试,非常合适,只需要十几分钟,就能把压力测试需要的脚本写好. 阅读目录 什么是压力 ...

  9. 使用 JMeter 完成常用的压力测试 [转]

    讲到测试,人们脑海中首先浮现的就是针对软件正确性的测试,即常说的功能测试.但是软件仅仅只是功能正确是不够的.在实际开发中,还有其它的非功能因素也起着决定性的因素,例如软件的响应速度.影响软件响应速度的 ...

随机推荐

  1. Namespace, string, vector and array

    1. Headers should not include using declaration Code inside headers ordinarily should not include us ...

  2. **php队列的实现思路和详细过程

    http://www.imooc.com/wenda/detail/252185 一.队列使用场景:为什么需要队列在web开发中,我们经常会遇到需要处理批量任务的时候,这些批量任务可能是用户提交的,也 ...

  3. hdu 4465 Candy 数学

    思路:易知结果为 ∑(n-k)*C(n+k,k)*(p^(n+1)*q^k+q^(n+1)*p^k). 注意不能直接算,注意点技巧!!!看代码 代码如下: #include<iostream&g ...

  4. HUSTOJ(转发)

    来源:http://blog.csdn.net/xiajian2010/article/details/12954855 缘起 大四了,快毕业了,所以想准备点LAMP的知识和经验.刚好实验室里有人在搞 ...

  5. lintcode:Valid Sudoku 判断数独是否合法

    题目: 判断数独是否合法 请判定一个数独是否有效.该数独可能只填充了部分数字,其中缺少的数字用 . 表示. 样例 下列就是一个合法数独的样例. 注意 一个合法的数独(仅部分填充)并不一定是可解的.我们 ...

  6. JavaWeb项目开发案例精粹-第3章在线考试系统-006实体层

    1. package com.sanqing.po; /* * 学生表,保存学生编号,系统密码 */ public class Student { private String studentID; ...

  7. Hibernate逍遥游记-第5章映射一对多-01单向<many-to-one>、cascade="save-update"、lazy、TransientObjectException

    1. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hi ...

  8. mac root用户初始密码设置

    具体方法如下: 1)sudo su切换到root,输入的用户密码是当前用户的密码: 2)切换到root后,执行passwd root,设置root用户密码即可.

  9. Android viewPage notifyDataSetChanged无刷新

    转载 http://www.67tgb.com/?p=624 最近项目结束,搞了一次代码分享.其中一位同学分享了一下自己在解决问题过程中的一些心得体会,感觉受益匪浅.整理出来,分享给大家. 建议使用自 ...

  10. poi操作oracle数据库导出excel文件

    HSSFWorkbook workBook = new HSSFWorkbook();// 创建 一个excel文档对象 HSSFSheet sheet = workBook.createSheet( ...