在上文中提到通过读取配置文件中的数据,以此定制JMeter Slave的脚本分发路径(默认脚本路径,即参数文件相对路径父目录)。
此文,就以此为例进行实例说明。
通过阅读JMeter源码 core/src/org.apache.jmeter.JMeter.java 如下代码片段可知,其通过 private void initializeProperties(CLArgsParser parser) 方法初始化响应的系统、用户等设置。
JMeter.java对应初始化的方法源码如下所示:

1 private void initializeProperties(CLArgsParser parser) { 2 if (parser.getArgumentById(PROPFILE_OPT) != null) { 3 JMeterUtils.loadJMeterProperties(parser.getArgumentById(PROPFILE_OPT).getArgument()); 4 } else { 5 JMeterUtils.loadJMeterProperties(NewDriver.getJMeterDir() + File.separator 6 + "bin" + File.separator // $NON-NLS-1$
7 + "jmeter.properties");// $NON-NLS-1$
8 } 9
10 if (parser.getArgumentById(JMLOGFILE_OPT) != null){ 11 String jmlogfile=parser.getArgumentById(JMLOGFILE_OPT).getArgument(); 12 jmlogfile = processLAST(jmlogfile, ".log");// $NON-NLS-1$
13 JMeterUtils.setProperty(LoggingManager.LOG_FILE,jmlogfile); 14 } 15
16 JMeterUtils.initLogging(); 17 JMeterUtils.initLocale(); 18 // Bug 33845 - allow direct override of Home dir
19 if (parser.getArgumentById(JMETER_HOME_OPT) == null) { 20 JMeterUtils.setJMeterHome(NewDriver.getJMeterDir()); 21 } else { 22 JMeterUtils.setJMeterHome(parser.getArgumentById(JMETER_HOME_OPT).getArgument()); 23 } 24
25 Properties jmeterProps = JMeterUtils.getJMeterProperties(); 26 remoteProps = new Properties(); 27
28 // Add local JMeter properties, if the file is found
29 String userProp = JMeterUtils.getPropDefault("user.properties",""); //$NON-NLS-1$
30 if (userProp.length() > 0){ //$NON-NLS-1$
31 FileInputStream fis=null; 32 try { 33 File file = JMeterUtils.findFile(userProp); 34 if (file.canRead()){ 35 log.info("Loading user properties from: "+file.getCanonicalPath()); 36 fis = new FileInputStream(file); 37 Properties tmp = new Properties(); 38 tmp.load(fis); 39 jmeterProps.putAll(tmp); 40 LoggingManager.setLoggingLevels(tmp);//Do what would be done earlier
41 } 42 } catch (IOException e) { 43 log.warn("Error loading user property file: " + userProp, e); 44 } finally { 45 JOrphanUtils.closeQuietly(fis); 46 } 47 } 48
49 // Add local system properties, if the file is found
50 String sysProp = JMeterUtils.getPropDefault("system.properties",""); //$NON-NLS-1$
51 if (sysProp.length() > 0){ 52 FileInputStream fis=null; 53 try { 54 File file = JMeterUtils.findFile(sysProp); 55 if (file.canRead()){ 56 log.info("Loading system properties from: "+file.getCanonicalPath()); 57 fis = new FileInputStream(file); 58 System.getProperties().load(fis); 59 } 60 } catch (IOException e) { 61 log.warn("Error loading system property file: " + sysProp, e); 62 } finally { 63 JOrphanUtils.closeQuietly(fis); 64 } 65 } 66
67 // Process command line property definitions 68 // These can potentially occur multiple times
69
70 List<CLOption> clOptions = parser.getArguments(); 71 for (CLOption option : clOptions) { 72 String name = option.getArgument(0); 73 String value = option.getArgument(1); 74 FileInputStream fis = null; 75
76 switch (option.getDescriptor().getId()) { 77
78 // Should not have any text arguments
79 case CLOption.TEXT_ARGUMENT: 80 throw new IllegalArgumentException("Unknown arg: " + option.getArgument()); 81
82 case PROPFILE2_OPT: // Bug 33920 - allow multiple props
83 try { 84 fis = new FileInputStream(new File(name)); 85 Properties tmp = new Properties(); 86 tmp.load(fis); 87 jmeterProps.putAll(tmp); 88 LoggingManager.setLoggingLevels(tmp);//Do what would be done earlier
89 } catch (FileNotFoundException e) { 90 log.warn("Can't find additional property file: " + name, e); 91 } catch (IOException e) { 92 log.warn("Error loading additional property file: " + name, e); 93 } finally { 94 JOrphanUtils.closeQuietly(fis); 95 } 96 break; 97 case SYSTEM_PROPFILE: 98 log.info("Setting System properties from file: " + name); 99 try { 100 fis = new FileInputStream(new File(name)); 101 System.getProperties().load(fis); 102 } catch (IOException e) { 103 log.warn("Cannot find system property file " + e.getLocalizedMessage()); 104 } finally { 105 JOrphanUtils.closeQuietly(fis); 106 } 107 break; 108 case SYSTEM_PROPERTY: 109 if (value.length() > 0) { // Set it
110 log.info("Setting System property: " + name + "=" + value); 111 System.getProperties().setProperty(name, value); 112 } else { // Reset it
113 log.warn("Removing System property: " + name); 114 System.getProperties().remove(name); 115 } 116 break; 117 case JMETER_PROPERTY: 118 if (value.length() > 0) { // Set it
119 log.info("Setting JMeter property: " + name + "=" + value); 120 jmeterProps.setProperty(name, value); 121 } else { // Reset it
122 log.warn("Removing JMeter property: " + name); 123 jmeterProps.remove(name); 124 } 125 break; 126 case JMETER_GLOBAL_PROP: 127 if (value.length() > 0) { // Set it
128 log.info("Setting Global property: " + name + "=" + value); 129 remoteProps.setProperty(name, value); 130 } else { 131 File propFile = new File(name); 132 if (propFile.canRead()) { 133 log.info("Setting Global properties from the file " + name); 134 try { 135 fis = new FileInputStream(propFile); 136 remoteProps.load(fis); 137 } catch (FileNotFoundException e) { 138 log.warn("Could not find properties file: " + e.getLocalizedMessage()); 139 } catch (IOException e) { 140 log.warn("Could not load properties file: " + e.getLocalizedMessage()); 141 } finally { 142 JOrphanUtils.closeQuietly(fis); 143 } 144 } 145 } 146 break; 147 case LOGLEVEL: 148 if (value.length() > 0) { // Set category
149 log.info("LogLevel: " + name + "=" + value); 150 LoggingManager.setPriority(value, name); 151 } else { // Set root level
152 log.warn("LogLevel: " + name); 153 LoggingManager.setPriority(name); 154 } 155 break; 156 case REMOTE_STOP: 157 remoteStop = true; 158 break; 159 default: 160 // ignored
161 break; 162 } 163 } 164
165 String sampleVariables = (String) jmeterProps.get(SampleEvent.SAMPLE_VARIABLES); 166 if (sampleVariables != null){ 167 remoteProps.put(SampleEvent.SAMPLE_VARIABLES, sampleVariables); 168 } 169 jmeterProps.put("jmeter.version", JMeterUtils.getJMeterVersion()); 170 }
通过源码可以看出 jmeter.properties、user.properties、system.properties均被系统获取,并最终保存在 org.apache.jmeter.util.JMmeterUtils.java 类中的appProperties 这个私有变量中,我们可通过 JMeterUtils.java 类中如下方法获取我们想要获取的值。
下面就通过定制JMeter Slave的脚本分发路径实例演示(相关命令请参阅上文)。
一、FileServer.java 源码修改及编译,生成class文件
1、新增方法
/**
* Get slave home for set base by fanfengping 2016-06-21
* <p>
*
* Reset base to SLAVE_ARG_HOME or JMETER_HOME when jmxBase is '.'.
*/
public File getSlaveBaseHome() {
String slaveArgHome = JMeterUtils.getPropDefault("SLAVE_ARG_HOME", "");
File jmeterHomeBase = new File(JMeterUtils.getJMeterHome());
if ("".equals(slaveArgHome)) {
return jmeterHomeBase;
} else {
return new File(slaveArgHome);
}
}
2、修改 setBase 方法
/**
* Sets the current base directory for relative file names.
*
* @param jmxBase the path of the script file base directory, cannot be null
* @throws IllegalStateException if files are still open
* @throws IllegalArgumentException if {@code basepath} is null
*/
public synchronized void setBase(File jmxBase) {
if (jmxBase == null) {
throw new IllegalArgumentException("jmxBase must not be null");
}
checkForOpenFiles();
// base = jmxBase;
/**
* fanfengping 2016-06-21
*/
base = ".".equals("" + jmxBase) ? getSlaveBaseHome() : jmxBase;
log.info("setBase Set new base='"+base+"'");
}
3、修改 setBaseDir 方法
/**
* Sets the current base directory for relative file names from the provided path.
* If the path does not refer to an existing directory, then its parent is used.
* Normally the provided path is a file, so using the parent directory is appropriate.
*
* @param basedir the path to set, or {@code null} if the GUI is being cleared
* @throws IllegalStateException if files are still open
*/
public synchronized void setBasedir(String basedir) {
checkForOpenFiles(); // TODO should this be called if basedir == null?
if (basedir != null) {
File newBase = new File(basedir);
if (!newBase.isDirectory()) {
newBase = newBase.getParentFile();
}
// base = newBase;
/**
* fanfengping 2016-06-21
*/
base = ".".equals("" + newBase) ? getSlaveBaseHome() : newBase;
log.info("setBasedir Set new base='"+base+"'");
}
}
二、ApacheJMeter_core.jar重新打包
将新生成的class文件拷贝至对应目录,重新打包 ApacheJMeter_core.jar,并替换JMETER_HOME/lib/ext 下的源文件。
三、user.properties配置文件修改
在文件末尾添加:SLAVE_ARG_HOME=E:/jmeter/script/,并在对应目录放置相应的参数文件 distributed.csv。
在D盘根目录下,重新执行启动JMeter服务命令:jmeter -s
四、执行脚本
jmeter -n -t JMeter分布式测试参数化示例.jmx -r -l report.csv -j remote.log
执行结果如下所示:
三、查看Slave服务日志
当SLAVE_ARG_HOME=E:/jmeter/script/时,日志如下所示:
当SLAVE_ARG_HOME不存在或为空时,日志如下所示:
由此可见,配置已生效,且JMeter脚本能够成功执行。
PS:暂未发现修改 base 后有其他的什么问题出现。若有发现因此产生的问题,敬请留言告知,不胜感激!
至此,此文顺利完结,希望此文能够给初学 JMeter 的您一份参考。
最后,非常感谢亲的驻足,希望此文能对亲有所帮助。热烈欢迎亲一起探讨,共同进步。非常感谢! ^_^