一、一语道破jmeter
 
    大家都知道我们在应用jmeter的图形化界面来进行操作,保存后生成的是一个.jmx文件。
    那么这个.jmx文件中都是些什么呢。
 
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" 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="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
    这是我截取的一段.jmx文件中的内容。
 
从文件中的第一行内容,<?xml version="1.0" encoding="UTF-8"?>
我们就可以很容易的看出来,这就是一个xml文件。一般在java开发中,我们使用这个文件来做配置文件。
 
综上,其实我们在jmeter的图形化界面的所有操作,其实就是在进行配置文件的配置,当然如果你对这个配置文件的书写规范足够熟悉的话就可以抛弃jmeter的GUI了。哈哈,不过这个得需要相当熟悉它的书写规范了。不过,不知道为什么,这个xml没有明确标注出来遵循哪个

XML Schema,使得我们如果我们真的要完全进行配置文件的操作的话会很有难度,不过我猜也没有人会这么做,因为这也太无聊了。

知道了这些,那么其实我们就可以知道我们在jmeter做的所有操作,它的代码是如何运行的了。结合API会使我们阅读源码更容易。
 
二、解析jmx文件
 
        这是我截取的一段我们添加的线程组的.jmx文件中的内容,是一个java请求的jmx配置信息
   <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="Sleep_Time" elementType="Argument">
<stringProp name="Argument.name">Sleep_Time</stringProp>
<stringProp name="Argument.value">100</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="Sleep_Mask" elementType="Argument">
<stringProp name="Argument.name">Sleep_Mask</stringProp>
<stringProp name="Argument.value">0xFF</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="Label" elementType="Argument">
<stringProp name="Argument.name">Label</stringProp>
<stringProp name="Argument.value"></stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="ResponseCode" elementType="Argument">
<stringProp name="Argument.name">ResponseCode</stringProp>
<stringProp name="Argument.value"></stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="ResponseMessage" elementType="Argument">
<stringProp name="Argument.name">ResponseMessage</stringProp>
<stringProp name="Argument.value"></stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="Status" elementType="Argument">
<stringProp name="Argument.name">Status</stringProp>
<stringProp name="Argument.value">OK</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="SamplerData" elementType="Argument">
<stringProp name="Argument.name">SamplerData</stringProp>
<stringProp name="Argument.value"></stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="ResultData" elementType="Argument">
<stringProp name="Argument.name">ResultData</stringProp>
<stringProp name="Argument.value"></stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">org.apache.jmeter.protocol.java.test.JavaTest</stringProp>
</JavaSampler>
<hashTree/>
可以看出,一个java请求的整体是由一个hashTree标签进行标记的,事实上我们基本上所有的元素都是由hashTree进行标记的,个别的除外,如添加一个查看结果树,这个是由ResultCollector标签进行标记。 其中JavaSampler标签就是标记这是一个java请求,直译为java取样器。
 
三、GUI与jmx比对说明
        这个添加的java请求是jmeter源码中自带的一个例子,GUI添加后如图:
 
 
从这里再结合jmx文件中,我们不难看出变量的名称和jmx中标签的对应关系,如:
    Sleep_Time这个变量对应的jmx文件中的内容是:
 
              <elementProp name="Sleep_Time" elementType="Argument">
<stringProp name="Argument.name">Sleep_Time</stringProp>
<stringProp name="Argument.value">100</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
其中,stringProp标签中,属性 name="Argument.name" 的值就是Sleep_Time
          stringProp标签中,属性 name="Argument.value" 的值就是变量Sleep_Time的值
          <stringProp name="Argument.metadata">=</stringProp> 这个标签说的是变量Sleep_Time和100的关系是等于。
 
其他的部分与此相同,就不一一进行解读了。 
 
四、源码解读
 
/**这个包名,也是这个文件所在的路径,java自带的一个演示文件,
英文好的同学可自行阅读,英文不好的可以和我一起阅读,
互相学习,共同进步,如有错误欢迎指正。
*/
package org.apache.jmeter.protocol.java.test; import java.io.Serializable;
import java.util.Iterator;
import java.util.concurrent.TimeUnit; 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.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger; public class JavaTest extends AbstractJavaSamplerClient implements Serializable { private static final Logger LOG = LoggingManager.getLoggerForClass(); private static final long serialVersionUID = 240L; /**这个变量是用来记录JavaSamplerContext对象context调用getLongParameter方法传递DEFAULT_SLEEP_TIME和SLEEP_NAME运算后的返回值*/
private long sleepTime; /** 下边这个变量的值100就是Sleep_Time的默认值,也是我们在页面中看到的那个100,注意这个值是一个毫秒值. */
public static final long DEFAULT_SLEEP_TIME = 100; /** 这个变量就是用来存储GUI中的那个Sleep_Time的变量。 */
private static final String SLEEP_NAME = "Sleep_Time"; /**
以下的变量名称和GUI中的变量名称都是相同的,不难看懂。
*/
private long sleepMask; public static final long DEFAULT_SLEEP_MASK = 0xff; private static final String DEFAULT_MASK_STRING = "0x" + (Long.toHexString(DEFAULT_SLEEP_MASK)).toUpperCase(java.util.Locale.ENGLISH); private static final String MASK_NAME = "Sleep_Mask"; private String label; private static final String LABEL_NAME = "Label"; private String responseMessage; private static final String RESPONSE_MESSAGE_DEFAULT = ""; private static final String RESPONSE_MESSAGE_NAME = "ResponseMessage"; private String responseCode; private static final String RESPONSE_CODE_DEFAULT = ""; private static final String RESPONSE_CODE_NAME = "ResponseCode"; private String samplerData; private static final String SAMPLER_DATA_DEFAULT = ""; private static final String SAMPLER_DATA_NAME = "SamplerData"; private String resultData; private static final String RESULT_DATA_DEFAULT = ""; private static final String RESULT_DATA_NAME = "ResultData"; private boolean success; private static final String SUCCESS_DEFAULT = "OK"; private static final String SUCCESS_NAME = "Status"; /**
* 默认的构造函数,实例化了一个客户端的类
*/
public JavaTest() {
LOG.debug(whoAmI() + "\tConstruct");
} /*
* 这个方法就是设置了所有的值,我们从GUI中输入的值就是由这个方法进行读取并且赋值给上边定义的变量。
*/
private void setupValues(JavaSamplerContext context) { sleepTime = context.getLongParameter(SLEEP_NAME, DEFAULT_SLEEP_TIME);
sleepMask = context.getLongParameter(MASK_NAME, DEFAULT_SLEEP_MASK); responseMessage = context.getParameter(RESPONSE_MESSAGE_NAME, RESPONSE_MESSAGE_DEFAULT); responseCode = context.getParameter(RESPONSE_CODE_NAME, RESPONSE_CODE_DEFAULT); success = context.getParameter(SUCCESS_NAME, SUCCESS_DEFAULT).equalsIgnoreCase("OK"); label = context.getParameter(LABEL_NAME, "");
if (label.length() == 0) {
label = context.getParameter(TestElement.NAME);
} samplerData = context.getParameter(SAMPLER_DATA_NAME, SAMPLER_DATA_DEFAULT); resultData = context.getParameter(RESULT_DATA_NAME, RESULT_DATA_DEFAULT);
} /**
这是一个初始化方法,可以理解为loadrunner中的init
*/
@Override
public void setupTest(JavaSamplerContext context) {
if (LOG.isDebugEnabled()) {
LOG.debug(whoAmI() + "\tsetupTest()");
listParameters(context);
}
} /**
这个方法是一个与生命周期相关的方法
决定了哪些变量参数是否显示到GUI页面上。这个方法类一加载就会运行,运行的顺序排在所有复写的方法中第一。
*/
@Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument(SLEEP_NAME, String.valueOf(DEFAULT_SLEEP_TIME));
params.addArgument(MASK_NAME, DEFAULT_MASK_STRING);
params.addArgument(LABEL_NAME, "");
params.addArgument(RESPONSE_CODE_NAME, RESPONSE_CODE_DEFAULT);
params.addArgument(RESPONSE_MESSAGE_NAME, RESPONSE_MESSAGE_DEFAULT);
params.addArgument(SUCCESS_NAME, SUCCESS_DEFAULT);
params.addArgument(SAMPLER_DATA_NAME, SAMPLER_DATA_DEFAULT);
params.addArgument(RESULT_DATA_NAME, SAMPLER_DATA_DEFAULT);
return params;
} /**
主要运行的代码,相当于Loadrunner中的action
*/
@Override
public SampleResult runTest(JavaSamplerContext context) {
setupValues(context); SampleResult results = new SampleResult(); results.setResponseCode(responseCode);
results.setResponseMessage(responseMessage);
results.setSampleLabel(label); if (samplerData != null && samplerData.length() > 0) {
results.setSamplerData(samplerData);
} if (resultData != null && resultData.length() > 0) {
results.setResponseData(resultData, null);
results.setDataType(SampleResult.TEXT);
} //这个方法很重要,是标记一个事务的开始,可以理解为loadrunner中的lr_start_transaction
results.sampleStart(); long sleep = sleepTime;
if (sleepTime > 0 && sleepMask > 0) {
long start = System.currentTimeMillis(); sleep = sleepTime + (start % sleepMask);
} try { if (sleep > 0) {
TimeUnit.MILLISECONDS.sleep(sleep);
}
results.setSuccessful(success);
} catch (InterruptedException e) {
LOG.warn("JavaTest: interrupted.");
results.setSuccessful(true);
} catch (Exception e) {
LOG.error("JavaTest: error during sample", e);
results.setSuccessful(false);
} finally {
// 这里就是标记事务的结束,相当于loadrunner中的lr_end_transaction
results.sampleEnd();
} if (LOG.isDebugEnabled()) {
LOG.debug(whoAmI() + "\trunTest()" + "\tTime:\t" + results.getTime());
listParameters(context);
} return results;
} /**
包含初始化参数的一个调试方法。
*/
private void listParameters(JavaSamplerContext context) {
Iterator<String> argsIt = context.getParameterNamesIterator();
while (argsIt.hasNext()) {
String name = argsIt.next();
LOG.debug(name + "=" + context.getParameter(name));
}
} /**
这个就是一个用户自定义的调试方法。
*/
private String whoAmI() {
StringBuilder sb = new StringBuilder();
sb.append(Thread.currentThread().toString());
sb.append("@");
sb.append(Integer.toHexString(hashCode()));
return sb.toString();
} } //还有一个常见方法,这里没有写出来,那就是 teardownTest,这个其实就可以理解为loadrunner中的end

至此,比较基本的东西都已说完,欢迎补充,共同学习。

更深层次的东西还需进一步阅读源代码,了解原理。

 

jmeter之GUI运行原理的更多相关文章

  1. 【转】Jmeter之GUI运行原理

    一.一语道破jmeter 大家都知道我们在应用jmeter的图形化界面来进行操作,保存后生成的是一个.jmx文件. 那么这个.jmx文件中都是些什么呢. <?xml version=" ...

  2. Jmeter非GUI运行,生成html报告

    一.JMete执行方式 JMeter执行方式有2种,一种是GUI模式,一种是非GUI模式.GUI模式就是界面模式,非GUI模式就是命令行模式.界面模式主要用来编写和调试脚本用的,项目的真正执行最好是采 ...

  3. JMeter实战(二) 运行原理

    运行原理 如果不用工具,要做 100 并发的压力测试,得想办法组织 100 个人,每个人操作1台电脑,一声令下,100 个人同时点击,对系统造成 100 并发.现实中,很难找 100 个人和 100 ...

  4. Jmeter运行原理

    Jmeter运行原理: JMETER是运行在JVM虚拟机上的,每个进程的开销比loadrunner的进程开销大,如果以进程的方式来运行每台负载机上的进程数量不会允许太多,当有大量并发时就需要大量的负载 ...

  5. jmeter的运行原理和测试计划要素

    jmeter运行原理 1.jmeter运行在JVM虚拟机上,jmeter是以线程的方式运行的. 2.jmeter通过线程组来驱动多个线程,运行测试脚本对被测试服务器发起负载,每一个负载机上够可以运行多 ...

  6. JMeter非GUI方式运行时动态设置线程组及传参

    http://blog.csdn.net/selingchen/article/details/48106517 在使用JMeter进行性能测试自动化时,可能会有如下需求: 1.指定运行多少线程,指定 ...

  7. Jmeter结构体系及运行原理

    Jmeter结构体系 把Jmeter的结构体系拆分为三维空间,如图: X1~X5:是负载模拟的一个过程,使用这些组件来完成负载的模拟: X1:选择协议,模拟用户请求,检查服务器响应是否正确,然后收集结 ...

  8. JMeter非GUI界面运行

    JMeter是一款可以用于做接口可以用于作压力性能的应用程序,该程序是纯Java语音开发,所有对环境支持都比较好. JMeter可以运行模式有两种,一种是UI图形,另一种是命令模式运行也就是非GUI模 ...

  9. 『动善时』JMeter基础 — 55、JMeter非GUI模式运行

    目录 1.JMeter的非GUI模式说明 2.为什么使用非GUI模式运行JMeter 3.怎样使用非GUI模式运行JMeter (1)非GUI模式运行JMeter步骤 (2)其它参数说明 4.CLI模 ...

随机推荐

  1. 试DG周围环境

    试DG周围环境 周围环境 名称 主库 备库 主机名 bjsrv shsrv 软件版本号 RedHat Enterprise5.5.Oracle 11g 11.2.0.1 RedHat Enterpri ...

  2. 十天学会php第五天

    学习目标:学会读取数据    先看两个函数:    1.mysql_query    送出一个 query 字符串. 语法   : int mysql_query(string query, int ...

  3. Servlet实例解说

    打开昨天上午,负责人突然问我,client控制信息,如何让在后台?我想回答:假设总体提交form,在C#使用代码request获取表单的内容.假设局部提交,在用JS和Ajax交互,通过Ajax的ope ...

  4. LightOJ 1205 Palindromic Numbers

    数位DP.... Palindromic Numbers Time Limit: 2000MS Memory Limit: 32768KB 64bit IO Format: %lld & %l ...

  5. Linux下一个CD翻录 创CUE 压缩flac攻略

    于Windows我们通常使用较低EAC翻录压缩发生器CUE找工作的步骤,但在Linux在稍微有点麻烦.每一步,我们需要自己做.经过我的反复尝试寻找和总结了相当不错的方法,使用软件和步骤如下面的. 使用 ...

  6. 关于int全区变量读写的原子性

    关于int全区变量读写的原子性     关于int变量的读写是否原子性网上有非常多讨论,貌似不同平台不同,这里自己做实如今arm9平台測试.这里要注意原子性并不是指一条汇编才原子,实际上即使一次赋值编 ...

  7. hadoop2.0的datanode数据存储文件夹策略的多个副本

    在hadoop2.0在,datanode数据存储盘选择策略有两种方式复制: 首先是要遵循hadoop1.0磁盘文件夹投票,实现类:RoundRobinVolumeChoosingPolicy.java ...

  8. hdu 4870 Rating(可能性DP&amp;高数消除)

    Rating Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  9. (大数据工程师学习路径)第二步 Vim编辑器----高级功能入门

    一.多文件编辑 1.使用vim编辑多个文件 编辑多个文件有两种形式,一种是在进入vim前使用的参数就是多个文件.另一种就是进入vim后再编辑其他的文件. 同时创建两个新文件并编辑 $ vim 1.tx ...

  10. Codeforces Round #257 (Div. 2/A)/Codeforces450A_Jzzhu and Children

    解题报告 没什么好说的,大于m的往后面放,,,re了一次,,, #include <iostream> #include <cstdio> #include <cstri ...