最近需要对改造的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. POJ1258Agri-Net

    http://poj.org/problem?id=1258 题意 : john当上了镇长,打算给每个农场都连接网络,需要用最小的成本连接其他所有农场,所以要找最少的纤维连在一起,任何两个农场之间的距 ...

  2. 用cxSelect插件补充一下回显过滤项功能

    这个在DJANGO里,最好在过滤之后,让用户知道自己过滤的选择.所以要定位默认值. 1,在HTML文件里显示默认值: <form class="uk-form" name=& ...

  3. 360 chrome 国际版能够隐藏用户保存的密码

    用360 chrome 国际版一段时间了,今天发现它一个优点:取消了浏览器保存的密码明文显示! 原生的chrome和枫树都会明文显示密码,360 chrome国际版则只显示保存了密码的域名和账户名.光 ...

  4. PHP中的多态

    多态的概念一般是强类型语言来谈的,因为强类型语言它必须要声明参数类型,比如一个手电筒对象的打开方法其参数申明了只能是蓝光,就不能传其他光.但可以用父类渲染的方式使其多态,比如声明一个光的父类,让其它颜 ...

  5. emms指令在MMX指令中的作用

    emms指令在MMX指令中的作用 转自:http://blog.csdn.net/psusong/archive/2009/01/08/3737047.aspx MMX和SSE都是INTEL开发的基于 ...

  6. Photoshop:建议设置

    一.新建文档设置: 二.对齐设置 菜单->视图->对齐->全部 使用图层.形状等操作时自动对齐网格,画矢量图不怕模糊边缘,确保每个像素保持清晰. 三.首选项设置 关掉"启用 ...

  7. iOS Objective-C对象模型及应用

    前言 原创文章,转载请注明出自唐巧的技术博客. 本文主要介绍Objective-C对象模型的实现细节,以及Objective-C语言对象模型中对isa swizzling和method swizzli ...

  8. jQuery插件开发(转)

    jQuery插件开发 - 其实很简单 [前言]jQuery已经被广泛使用,凭借其简洁的API,对DOM强大的操控性,易扩展性越来越受到web开发人员的喜爱,我在社区也发布了很多的jQuery插件,经常 ...

  9. NSArray 迭代

    NSObject *obj=[[NSObject alloc]init];        NSArray *array=[[NSArray alloc] initWithObjects:@" ...

  10. Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.

    在部署的时候出现Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server ...