我正在开发一个JMeter测试计划,用于对Web服务进行性能测试。整个测试计划的主要部分包括两个步骤。
如果我使用单线程计划,一切都按预期进行,但只要我使用多个线程,就会陷入竞争状态。问题是,第二步更改了可用ID列表,因此:如果线程B在线程A完成步骤2之前检索ID列表,则线程B可能获得与线程A相同的ID,这导致线程B出错试图完成第2步。不知何故,这是多线程环境中竞争条件的经典例子。 由于JMeter没有提供定义关键代码块的可能性,我决定编写自己的自定义Java采样器,扩展JMeter-AbstractJavaSamplerClient,覆盖runTest()a.s.o.在runTest() - 实现中,我获取了一个ReentrantLock并使用它来锁定关键代码块。关键是,JMeter似乎并不关心那个锁,我根本就不明白为什么......如果我通过远程调试使用Eclipse调试我的代码我看到几个线程同时进入锁定的代码,情况不应该如此。我也尝试了使用synchronize进行完整的runTest() - 实现的老式方法,但这也不起作用。
有没有人有什么需要改变的建议?或者至少解释为什么这不起作用?
提前致谢!
答案 0 :(得分:2)
另一种解决方法是编译一个简单的java类,编译它并将其放入{JMETER_HOME}\apache-jmeter-3.1\lib\ext\
文件夹。
import java.util.*;
public class Global {
public static Map map = new Hashtable();
}
使用CMD将其导出到jar文件中
jar cvfe {EXPORT_JAR_NAME}.jar ClassName {CLASS_FILE_NAME}.class
将文件放入{JMETER_HOME}\apache-jmeter-3.1\lib\ext\
文件夹。
创建测试操作并将JSR223 PreProcessor添加到测试计划中 Show Image
import java.util.concurrent.Semaphore;
Global.map.clear();
Global.map.put("sem", new Semaphore(1));;
创建另一个测试操作并将JSR223 PreProcessor添加到测试计划中Show Image
log.info(ctx.getThreadNum() + " ACQUIRE");
Global.map.get("sem").acquire();
for (def i = 0; i < 100; i++) {
// Do something
log.info(ctx.getThreadNum() + " DO SOMETHING " + i);
}
Global.map.get("sem").release();
log.info(ctx.getThreadNum() + " RELEASE");
它应该克服竞争条件,因为信号量在线程组之间同步。
答案 1 :(得分:0)
如何在不必编写自己的采样器的情况下处理它有两个选项。
任何Beanshell测试元素(采样器,后处理器,预处理器,断言等)都可以访问名为vars
的内容,这是JMeterVariables类实例的简写。所以你应该可以使用:
vars.put("key", "value"); // to add a variable
vars.remove("key"); // to remove variable
测试中的任何地方的方法。
有关Beanshell食谱的详细信息和种类,请参阅How to use BeanShell: JMeter's favorite built-in component指南。
答案 2 :(得分:0)
我终于让它运行了...我没有声明我的Lock是静态的...因此有几个线程可能进入关键代码块。