JMeter tooling for performance cluster (#110)

* First working version of RPC & JMeter

* Remote JMeter working from single JAR.

* Some clean up.  Remote slave via capsule is working.

* Full config of capsule launched JMeter server (was missing functions previously).

* SSH tunnelling utility.  Property files per remote host.

* Rename jar to make easier to deploy with wildcard filters.

* Easy all in one launch of UI + SSH tunnels.

* Comment out parties.

* Work around for notary.

* Clean up, renaming etc

* Add some comments and clean up.

* Add some comments and clean up.

* README and fixes.

* Redirect search_paths into a file since it so long and doesn't work on the command line in Windows.

* First working version of RPC & JMeter

* Remote JMeter working from single JAR.

* Some clean up.  Remote slave via capsule is working.

* Full config of capsule launched JMeter server (was missing functions previously).

* SSH tunnelling utility.  Property files per remote host.

* Easy all in one launch of UI + SSH tunnels.

* Comment out parties.

* Work around for notary.

* Clean up, renaming etc

* Add some comments and clean up.

* Add some comments and clean up.

* README and fixes.

* Reduce the dependencies of the JMeter project by copying (#118)

one function and listing required explicit dependencies
instead of depending on loadtest

* Tidy up

* Fix ssh for windows (#121)

* Make ssh tunnels work with Pageant on windows and allow specifying explicit
ssh remote user

* Update comments
This commit is contained in:
Rick Parker 2017-11-23 12:17:10 +00:00 committed by GitHub
parent 855c22218a
commit 3061678305
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2599 additions and 0 deletions

2
.idea/compiler.xml generated
View File

@ -77,6 +77,8 @@
<module name="jfx_integrationTest" target="1.8" />
<module name="jfx_main" target="1.8" />
<module name="jfx_test" target="1.8" />
<module name="jmeter_main" target="1.8" />
<module name="jmeter_test" target="1.8" />
<module name="kryo-hook_main" target="1.8" />
<module name="kryo-hook_test" target="1.8" />
<module name="loadtest_main" target="1.8" />

View File

@ -34,6 +34,7 @@ include 'tools:explorer:capsule'
include 'tools:demobench'
include 'tools:loadtest'
include 'tools:graphs'
include 'tools:jmeter'
include 'example-code'
project(':example-code').projectDir = file("$settingsDir/docs/source/example-code")
include 'samples:attachment-demo'

57
tools/jmeter/README.md Normal file
View File

@ -0,0 +1,57 @@
This module contains gradle tasks to make running the JMeter (http://jmeter.apache.org)
load generation tool against Corda nodes much easier and more useful. It does this by
providing a simple way to launch JMeter with the actual JMeter install coming
from downloaded dependencies, and by providing some Samplers that interact with
the Corda node via RPC.
To run up the JMeter UI, using the jmeter.properties in the resources folder,
type the following:
`./gradlew tools:jmeter:run`
You can then open the example script in "Example Flow Properties.jmx" via the File -> Open menu option. You need to
configure the host, ports, user name and password in the Java Sampler that correspond to your chosen target Corda node.
Simply running from the UI will result in the RPC client running inside the UI JVM.
If you wish to pass additional arguments to JMeter, you can do this:
`./gradlew tools:jmeter:run -PjmeterArgs="['-n', '-Ljmeter.engine=DEBUG']"`
The intention is to run against a remote Corda node or nodes, hosted on servers rather than desktops. To
this end, we leverage the JMeter ability to run remote agents that actually execute the tests, with these
reporting results back to the UI (or headless process if you so desire - e.g. for automated benchmarks). This is
supplemented with some additional convenience of automatically creating ssh tunnels to the remote nodes
(we don't want the JMeter ports open to the internet) in coordination with the jmeter.properties.
The remote agents then run close to the nodes, so the latency of RPC calls is minimised.
A Capsule (http://www.capsule.io) based launchable JAR is created that can be run with the simple command line
`java -jar jmeter-corda-<version>.jar`
Embedded in the JAR is all of the corda code for flows and RPC, as well as the jmeter.propeties. This
JAR will also include a properties file based on the hostname in the JMeter configuration,
so we allocate different SSH tunneled port numbers this way.
To launch JMeter with the tunnels automatically created:
`./gradlew tools:jmeter:run -PjmeterHosts="['hostname1', 'hostname2']"`
The list of hostnames should be of at least length one, with a maximum equal to the length of the remote_hosts
option in jmeter.properties. We effectively "zip" together the hostnames and that list to build the SSH tunnels.
The remote_hosts property helps define the ports (the hosts should always be local) used
for each host listed in jmeterHosts. Some additional ports are also opened based on some other
parts of the configuration to access the RMI registry and to allow return traffic
from remote agents.
The SSH tunnels can be started independently with:
`./gradlew tools:jmeter:runSsh -PjmeterHosts="['hostname1', 'hostname2']"`
For the ssh tunneling to work, an ssh agent must be running on your local machine with the
appropriate private key loaded. If the environment variable `SSH_AUTH_SOCK` is set, the code
assumes that a posix sshagent process is being used, if it is not set, it assumes that
[Pageant](https://www.ssh.com/ssh/putty/putty-manuals/0.68/Chapter9.html) is in use. If the
remote user name is different from the current user name, `-XsshUser <remote user name>`
can be used to set this, or in the gradle call:
`./gradlew tools:jmeter:runSsh -PjmeterHosts="['hostname1', 'hostname2']" -PsshUser="'username'"`

138
tools/jmeter/build.gradle Normal file
View File

@ -0,0 +1,138 @@
apply plugin: 'kotlin'
apply plugin: 'us.kirchmeier.capsule'
apply plugin: 'application'
mainClassName = 'com.r3.corda.jmeter.Launcher'
dependencies {
compile project(':client:rpc')
compile project(':finance')
// https://mvnrepository.com/artifact/com.jcraft/jsch
compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
compile group: 'com.jcraft', name: 'jsch.agentproxy.core', version: '0.0.9'
compile group: 'com.jcraft', name: 'jsch.agentproxy.sshagent', version: '0.0.9'
compile group: 'com.jcraft', name: 'jsch.agentproxy.usocket-jna', version: '0.0.9'
compile group: 'com.jcraft', name: 'jsch.agentproxy.pageant', version: '0.0.9'
// Log4J: logging framework (with SLF4J bindings)
compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
compile "org.apache.logging.log4j:log4j-core:$log4j_version"
// JMeter
ext.jmVersion = "3.3"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_components', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_core', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_ftp', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_functions', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_http', version: "$jmVersion"
compile group: 'org.apache.jmeter', name: 'ApacheJMeter_java', version: "$jmVersion" // 'compile' because we extend Java sampler.
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_jdbc', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_jms', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_junit', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_ldap', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_mail', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_mongodb', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_native', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_tcp', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter_config', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'ApacheJMeter', version: "$jmVersion"
runtime group: 'org.apache.jmeter', name: 'jorphan', version: "$jmVersion"
}
// Run JMeter as server process/agent on current host.
task(runServer, dependsOn: 'classes', type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'com.r3.corda.jmeter.Launcher'
def file = new File("$rootDir/build/search_paths.txt")
file.createNewFile()
file.text = "${project(':tools:jmeter').configurations.runtime.files.join(";")}"
systemProperty "search_paths_file", file.toString()
systemProperty "java.rmi.server.hostname", "0.0.0.0"
systemProperty "jmeter.home", sourceSets.main.resources.getSrcDirs().first().getPath()
// If you want to debug: jvmArgs += "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
args+= [ "-p", sourceSets.main.resources.getSrcDirs().first().getPath()+"/jmeter.properties",
"-d", sourceSets.main.resources.getSrcDirs().first().getPath(),
"-s" ]
}
// Just start ssh tunnels, without JMeter.
task(runSsh, dependsOn: 'classes', type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'com.r3.corda.jmeter.Ssh'
if ( project.hasProperty("sshUser") ){
args+= "-XsshUser"
args+= Eval.me(sshUser)
}
if ( project.hasProperty("jmeterHosts") ) {
args+= "-Xssh"
args+= Eval.me(jmeterHosts)
}
standardInput = System.in
}
// Run JMeter (by default the UI).
// Extra args can be passed by setting jmeterArgs (e.g. -n to run in non-UI mode).
// e.g. ./gradlew tools:jmeter:run -PjmeterArgs="['-n']"
// ssh tunnels will be built from local host to remote hosts by specifying jmeterHosts
// e.g. ./gradlew tools:jmeter:run -PjmeterHosts="['perf-notary.corda.r3cev.com', 'perf-node-1.corda.r3cev.com']"
// Each host is paired with local host ports listed in remote_hosts of jmeter.properties
run {
def file = new File("$rootDir/build/search_paths.txt")
file.createNewFile()
file.text = "${project(':tools:jmeter').configurations.runtime.files.join(";")}"
systemProperty "search_paths_file", file.toString()
systemProperty "java.rmi.server.hostname", "localhost"
systemProperty "jmeter.home", sourceSets.main.resources.getSrcDirs().first().getPath()
// If you want to debug: jvmArgs += "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
args+= [ "-p", sourceSets.main.resources.getSrcDirs().first().getPath()+"/jmeter.properties",
"-d", sourceSets.main.resources.getSrcDirs().first().getPath() ]
if ( project.hasProperty("jmeterArgs") ) {
args+= Eval.me(jmeterHosts)
}
if ( project.hasProperty("sshUser") ){
args+= "-XsshUser"
args+= Eval.me(sshUser)
}
if ( project.hasProperty("jmeterHosts") ) {
args+= "-Xssh"
args+= Eval.me(jmeterHosts)
}
}
jar {
manifest {
attributes(
'Automatic-Module-Name': 'net.corda.tools.jmeter',
'Main-Class': mainClassName
)
}
zip64 = true
}
// For building a runnable jar with no other dependencies for remote JMeter slave server, that has Corda code on classpath.
// Run with: java -jar jmeter-corda-<version>.jar
// No additional args required but will be passed if specified.
task buildJMeterJAR(type: FatCapsule, dependsOn: 'jar') {
applicationClass 'com.r3.corda.jmeter.Launcher'
archiveName "jmeter-corda-${corda_release_version}.jar"
applicationSource = files(
project(':tools:jmeter').jar
)
from 'NOTICE' // Copy CDDL notice
from("$rootDir/tools/jmeter/build/resources/main") {
include "log4j2.xml"
include "*.properties"
}
capsuleManifest {
applicationVersion = corda_release_version
systemProperties['java.rmi.server.hostname'] = 'localhost'
minJavaVersion = '1.8.0'
minUpdateVersion['1.8'] = java8_minUpdateVersion
// JVM configuration. Can be overridden on java command line.
jvmArgs = ['-Xms512m', '-Xmx512m', '-XX:+UseG1GC']
}
}

View File

@ -0,0 +1,87 @@
package com.r3.corda.jmeter
import net.corda.client.rpc.CordaRPCClient
import net.corda.client.rpc.CordaRPCConnection
import net.corda.core.flows.FlowLogic
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.NetworkHostAndPort
import org.apache.jmeter.config.Argument
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
/**
* Do most of the work for firing flow start requests via RPC at a Corda node.
*/
abstract class BaseFlowSampler() : AbstractJavaSamplerClient() {
companion object {
val host = Argument("host", "localhost", "<meta>", "The remote network address (hostname or IP address) to connect to for RPC.")
val port = Argument("port", "10000", "<meta>", "The remote port to connect to for RPC.")
val username = Argument("username", "corda", "<meta>", "The RPC user to connect to connect as.")
val password = Argument("password", "corda_is_awesome", "<meta>", "The password for the RPC user.")
val allArgs = setOf(host, port, username, password)
}
var rpcClient: CordaRPCClient? = null
var rpcConnection: CordaRPCConnection? = null
var rpcProxy: CordaRPCOps? = null
override fun getDefaultParameters(): Arguments {
// Add copies of all args, since they seem to be mutable.
return Arguments().apply {
for (arg in allArgs) {
addArgument(arg.clone() as Argument)
}
for (arg in additionalArgs) {
addArgument(arg.clone() as Argument)
}
}
}
override fun setupTest(context: JavaSamplerContext) {
super.setupTest(context)
rpcClient = CordaRPCClient(NetworkHostAndPort(context.getParameter(host.name), context.getIntParameter(port.name)))
rpcConnection = rpcClient!!.start(context.getParameter(username.name), context.getParameter(password.name))
rpcProxy = rpcConnection!!.proxy
setupTest(rpcProxy!!, context)
}
override fun runTest(context: JavaSamplerContext): SampleResult {
val flowInvoke = createFlowInvoke(rpcProxy!!, context)
val result = SampleResult()
result.sampleStart()
val handle = rpcProxy!!.startFlowDynamic(flowInvoke!!.flowLogicClass, *(flowInvoke!!.args))
result.sampleLabel = handle.id.toString()
result.latencyEnd()
try {
val flowResult = handle.returnValue.get()
result.sampleEnd()
return result.apply {
isSuccessful = true
}
} catch (e: Exception) {
result.sampleEnd()
return result.apply {
isSuccessful = false
}
}
}
override fun teardownTest(context: JavaSamplerContext) {
teardownTest(rpcProxy!!, context)
rpcProxy = null
rpcConnection!!.close()
rpcConnection = null
rpcClient = null
super.teardownTest(context)
}
abstract val additionalArgs: Set<Argument>
abstract fun setupTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext)
abstract fun createFlowInvoke(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext): FlowInvoke<*>
abstract fun teardownTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext)
class FlowInvoke<T : FlowLogic<*>>(val flowLogicClass: Class<out T>, val args: Array<Any?>)
}

View File

@ -0,0 +1,63 @@
package com.r3.corda.jmeter
import com.jcraft.jsch.Buffer
import com.jcraft.jsch.Identity
import com.jcraft.jsch.IdentityRepository
import com.jcraft.jsch.JSch
import com.jcraft.jsch.agentproxy.AgentProxy
import com.jcraft.jsch.agentproxy.connector.PageantConnector
import com.jcraft.jsch.agentproxy.connector.SSHAgentConnector
import com.jcraft.jsch.agentproxy.usocket.JNAUSocketFactory
import org.slf4j.LoggerFactory
import java.util.*
private val log = LoggerFactory.getLogger(Ssh::class.java)
/**
* Creates a new [JSch] instance with identities loaded from the running SSH agent.
*/
fun setupJSchWithSshAgent(): JSch {
val connector =
if (System.getenv("SSH_AUTH_SOCK") == null)
PageantConnector()
else
SSHAgentConnector(JNAUSocketFactory())
val agentProxy = AgentProxy(connector)
val identities = agentProxy.identities
require(identities.isNotEmpty()) { "No SSH identities found, please add one to the agent" }
require(identities.size == 1) { "Multiple SSH identities found, don't know which one to pick" }
val identity = identities[0]
log.info("Using SSH identity ${String(identity.comment)}")
return JSch().apply {
identityRepository = object : IdentityRepository {
override fun getStatus(): Int {
if (connector.isAvailable) {
return IdentityRepository.RUNNING
} else {
return IdentityRepository.UNAVAILABLE
}
}
override fun getName() = connector.name
override fun getIdentities(): Vector<Identity> = Vector(listOf(
object : Identity {
override fun clear() {}
override fun getAlgName() = String(Buffer(identity.blob).string)
override fun getName() = String(identity.comment)
override fun isEncrypted() = false
override fun getSignature(data: ByteArray?) = agentProxy.sign(identity.blob, data)
@Suppress("OverridingDeprecatedMember")
override fun decrypt() = true
override fun getPublicKeyBlob() = identity.blob
override fun setPassphrase(passphrase: ByteArray?) = true
}
))
override fun remove(blob: ByteArray?) = throw UnsupportedOperationException()
override fun removeAll() = throw UnsupportedOperationException()
override fun add(bytes: ByteArray?) = throw UnsupportedOperationException()
}
}
}

View File

@ -0,0 +1,83 @@
package com.r3.corda.jmeter
import com.sun.javaws.exceptions.InvalidArgumentException
import net.corda.core.internal.div
import org.apache.jmeter.JMeter
import org.slf4j.LoggerFactory
import java.net.InetAddress
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.streams.asSequence
/**
* A wrapper around JMeter to make it run without having a JMeter download installed locally. One mode is used for
* running on a remote cluster using an all-in-one bundle JAR using Capsule. The other is just used to run based on current
* classpath, but with optional SSH tunnelling logic automatically invoked.
*/
class Launcher {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val logger = LoggerFactory.getLogger(this::class.java)
logger.info("Launcher called with ${args.toList()}")
val jmeter = JMeter()
val capsuleDir = System.getProperty("capsule.dir")
if (capsuleDir != null) {
// We are running under Capsule, so assume we want a JMeter slave server to be controlled from
// elsewhere.
logger.info("Starting JMeter in server mode from $capsuleDir")
val capsuleDirPath = Paths.get(capsuleDir)
// Add all JMeter and Corda jars onto the JMeter search_paths
val searchPath = Files.list(capsuleDirPath).asSequence().filter {
val filename = it.fileName.toString()
filename.endsWith(".jar") && (filename.contains("corda") || filename.contains("jmeter", true))
}.joinToString(";")
logger.info("search_paths = $searchPath")
System.setProperty("search_paths", searchPath)
// Set the JMeter home as a property rather than command line arg, due to inconsistent code in JMeter.
System.setProperty("jmeter.home", capsuleDir)
// Create two dirs that JMeter expects, if they don't already exist.
Files.createDirectories(capsuleDirPath / "lib" / "ext")
Files.createDirectories(capsuleDirPath / "lib" / "junit")
// Now see if we have a hostname specific property file, and if so, add it.
val hostName = InetAddress.getLocalHost().hostName
val hostSpecificConfigFile = capsuleDirPath / "$hostName.properties"
logger.info("Attempting to use host-specific properties file $hostSpecificConfigFile")
val extraArgs = if (Files.exists(hostSpecificConfigFile)) {
logger.info("Found host-specific properties file")
arrayOf("-q", hostSpecificConfigFile.toString())
} else {
emptyArray()
}
jmeter.start(arrayOf("-s", "-p", (capsuleDirPath / "jmeter.properties").toString()) + extraArgs + args)
} else {
jmeter.start(maybeOpenSshTunnels(args))
}
}
fun maybeOpenSshTunnels(args: Array<String>): Array<String> {
// We trim the args at the point "-Xssh" appears in the array of args. Anything after that is a host to
// SSH tunnel to. Also get and remove the "-XsshUser" argument if it appears.
var index = 0
var userName = System.getProperty("user.name")
val returnArgs = mutableListOf<String>()
while (index < args.size) {
if (args[index] == "-XsshUser") {
++index
if (index == args.size || args[index].startsWith("-")) {
throw InvalidArgumentException(args)
}
userName = args[index]
} else if (args[index] == "-Xssh") {
// start ssh
Ssh.createSshTunnels(args.copyOfRange(index + 1, args.size), userName, false)
return returnArgs.toTypedArray()
} else {
returnArgs.add(args[index])
}
index++
}
return returnArgs.toTypedArray()
}
}
}

View File

@ -0,0 +1,51 @@
package com.r3.corda.jmeter
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.OpaqueBytes
import net.corda.finance.DOLLARS
import net.corda.finance.flows.CashIssueFlow
import org.apache.jmeter.config.Argument
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext
/**
* A base sampler that looks up identities via RPC ready for starting flows, to be extended and specialised as required.
*/
abstract class AbstractSampler : BaseFlowSampler() {
lateinit var notaryIdentity: Party
companion object JMeterProperties {
val notary = Argument("notaryName", "", "<meta>", "The X500 name of the notary.")
}
protected fun getIdentities(rpc: CordaRPCOps, testContext: JavaSamplerContext) {
if (!testContext.containsParameter(notary.name)) {
throw IllegalStateException("You must specify the '${notary.name}' property.")
}
val notaryName = CordaX500Name.parse(testContext.getParameter(notary.name))
notaryIdentity = rpc.wellKnownPartyFromX500Name(notaryName) ?: throw IllegalStateException("Don't know $notaryName")
}
}
/**
* A sampler for calling CashIssueFlow.
*
* TODO: add more configurable parameters (reference, amount etc) if there is a requirement.
*/
class CashIssueSampler : AbstractSampler() {
override val additionalArgs: Set<Argument> = setOf(notary)
override fun setupTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext) {
getIdentities(rpcProxy, testContext)
}
override fun teardownTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext) {
}
override fun createFlowInvoke(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext): FlowInvoke<CashIssueFlow> {
val amount = 1_100_000_000_000.DOLLARS
return FlowInvoke<CashIssueFlow>(CashIssueFlow::class.java, arrayOf(amount, OpaqueBytes.of(1), notaryIdentity))
}
}

View File

@ -0,0 +1,135 @@
package com.r3.corda.jmeter
import com.jcraft.jsch.JSch
import com.jcraft.jsch.Session
import com.sun.javaws.exceptions.InvalidArgumentException
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.nodeapi.internal.addShutdownHook
import org.slf4j.LoggerFactory
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*
/**
* Creates SSH tunnels for remote controlling SSH servers/agents from the local host (via UI or headless).
*/
class Ssh {
companion object {
val log = LoggerFactory.getLogger(this::class.java)
@JvmStatic
fun main(args: Array<String>) {
// parse the args and call createSshTunnels
// the only arguments recognised are "-XsshUser" for the remote user name
// and "-Xssh" - everything after this will be treated as a remote host name
var userName = System.getProperty("user.name")
var index = 0
while (index < args.size) {
if (args[index] == "-XsshUser") {
++index
if (index == args.size || args[index].startsWith("-")) {
throw InvalidArgumentException(args)
}
userName = args[index]
} else if (args[index] == "-Xssh") {
createSshTunnels(args.copyOfRange(index + 1, args.size), userName, true)
return
}
}
log.info("Nothing to be done - did you specify hosts to tunnel to with -Xssh?")
}
fun createSshTunnels(hosts: Array<String>, userName: String, wait: Boolean) {
log.info("User name for ssh: ${userName}")
val jsch = setupJSchWithSshAgent()
val sessions = mutableListOf<Session>()
// Read jmeter.properties
// For each host:port combo, map them to hosts from command line
val jmeterProps = loadProps("/jmeter.properties")
// The port the JMeter remote agents call back to on this client host.
val clientRmiLocalPort = jmeterProps.getProperty("client.rmi.localport").toInt()
// Remote RMI registry port.
val serverRmiPort = jmeterProps.getProperty("server.rmi.port", "1099").toInt()
// Where JMeter driver will try to connect for remote agents (should all be localhost so can ssh tunnel).
val localHostsAndPorts = jmeterProps.getProperty("remote_hosts", "").split(',').map { it.trim() }
hosts.zip(localHostsAndPorts) { remoteHost, localHostAndPortString ->
// Actual remote host and port we will tunnel to.
log.info("Creating tunnels for $remoteHost")
val localHostAndPort = NetworkHostAndPort.parse(localHostAndPortString)
// For the remote host, load their specific property file, since it specifies remote RMI server port
val unqualifiedHostName = remoteHost.substringBefore('.')
val hostProps = loadProps("/$unqualifiedHostName.properties")
val serverRmiLocalPort = hostProps.getProperty("server.rmi.localport", jmeterProps.getProperty("server.rmi.localport")).toInt()
val session = connectToHost(jsch, remoteHost, userName)
sessions += session
// For tunnelling the RMI registry on the remote agent
// ssh ${remoteHostAndPort.host} -L 0.0.0.0:${localHostAndPort.port}:localhost:$serverRmiPort -N
createOutboundTunnel(session, NetworkHostAndPort("0.0.0.0", localHostAndPort.port), NetworkHostAndPort("localhost", serverRmiPort))
// For tunnelling the actual connection to the remote agent
// ssh ${remoteHostAndPort.host} -L 0.0.0.0:$serverRmiLocalPort:localhost:$serverRmiLocalPort -N
createOutboundTunnel(session, NetworkHostAndPort("0.0.0.0", serverRmiLocalPort), NetworkHostAndPort("localhost", serverRmiLocalPort))
// For returning results to the client
// ssh ${remoteHostAndPort.host} -R 0.0.0.0:clientRmiLocalPort:localhost:clientRmiLocalPort -N
createInboundTunnel(session, NetworkHostAndPort("0.0.0.0", clientRmiLocalPort), NetworkHostAndPort("localhost", clientRmiLocalPort))
}
if (wait) {
val input = BufferedReader(InputStreamReader(System.`in`))
do {
log.info("Type 'quit' to exit cleanly.")
} while (input.readLine() != "quit")
sessions.forEach {
log.info("Closing tunnels for ${it.host}")
it.disconnect()
}
} else {
addShutdownHook {
sessions.forEach {
log.info("Closing tunnels for ${it.host}")
it.disconnect()
}
}
}
}
private fun loadProps(filename: String): Properties {
val props = Properties()
this::class.java.getResourceAsStream(filename).use {
props.load(it)
}
return props
}
fun connectToHost(jSch: JSch, remoteHost: String, remoteUserName: String): Session {
val session = jSch.getSession(remoteUserName, remoteHost, 22)
// We don't check the host fingerprints because they may change often
session.setConfig("StrictHostKeyChecking", "no")
log.info("Connecting to $remoteHost...")
session.connect()
log.info("Connected to $remoteHost!")
return session
}
fun createOutboundTunnel(session: Session, local: NetworkHostAndPort, remote: NetworkHostAndPort) {
log.info("Creating outbound tunnel from $local to $remote with ${session.host}...")
session.setPortForwardingL(local.host, local.port, remote.host, remote.port)
log.info("Tunnel created!")
}
fun createInboundTunnel(session: Session, local: NetworkHostAndPort, remote: NetworkHostAndPort) {
log.info("Creating inbound tunnel from $remote to $local on ${session.host}...")
session.setPortForwardingR(remote.host, remote.port, local.host, local.port)
log.info("Tunnel created!")
}
}
}

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="3.2" jmeter="3.3 r1808647">
<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>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1000</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">3</stringProp>
<stringProp name="ThreadGroup.ramp_time"></stringProp>
<longProp name="ThreadGroup.start_time">1509455820000</longProp>
<longProp name="ThreadGroup.end_time">1509455820000</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="Cash Issue Request" enabled="true">
<elementProp name="arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="host" elementType="Argument">
<stringProp name="Argument.name">host</stringProp>
<stringProp name="Argument.value">localhost</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="port" elementType="Argument">
<stringProp name="Argument.name">port</stringProp>
<stringProp name="Argument.value">10003</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="username" elementType="Argument">
<stringProp name="Argument.name">username</stringProp>
<stringProp name="Argument.value">corda</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="password" elementType="Argument">
<stringProp name="Argument.name">password</stringProp>
<stringProp name="Argument.value">Password Here</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="notaryName" elementType="Argument">
<stringProp name="Argument.name">notaryName</stringProp>
<stringProp name="Argument.value">O=Perf-10.155.0.4, OU=Corda, L=London, C=GB</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueSampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
<ResultCollector guiclass="StatGraphVisualizer" testclass="ResultCollector" testname="Aggregate Graph" 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>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="GraphVisualizer" testclass="ResultCollector" testname="Graph Results" 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>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="TableVisualizer" testclass="ResultCollector" testname="View Results in Table" 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>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
<WorkBench guiclass="WorkBenchGui" testclass="WorkBench" testname="WorkBench" enabled="true">
<boolProp name="WorkBench.save">true</boolProp>
</WorkBench>
<hashTree/>
</hashTree>
</jmeterTestPlan>

View File

@ -0,0 +1,412 @@
#---------------------------------------------------------
# SAVESERVICE PROPERTIES - JMETER INTERNAL USE ONLY
#---------------------------------------------------------
## Licensed to the Apache Software Foundation (ASF) under one or more
## contributor license agreements. See the NOTICE file distributed with
## this work for additional information regarding copyright ownership.
## The ASF licenses this file to You under the Apache License, Version 2.0
## (the "License"); you may not use this file except in compliance with
## the License. You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
# This file is used to define how XStream (de-)serializes classnames
# in JMX test plan files.
# FOR JMETER INTERNAL USE ONLY
#---------------------------------------------------------
# N.B. To ensure backward compatibility, please do NOT change or delete any entries
# New entries can be added as necessary.
#
# Note that keys starting with an underscore are special,
# and are not used as aliases.
#
# Please keep the entries in alphabetical order within the sections
# to reduce the likelihood of duplicates
#
# version number of this file is now computed by a sha1 sum, so no need for
# an explicit _file_version property anymore.
#
# For this sha1 sum we ignore every newline character. It can be computed
# by the following command:
#
# cat bin/saveservice.properties | perl -ne 'chomp; print' | sha1sum
#
# Be aware, that every change in this file will change the sha1 sum!
#
# Conversion version (for JMX output files)
# Must be updated if the file has been changed since the previous release
# Format is:
# Save service version=JMeter version at which change occurred
# 1.7 = 2.1.1
# 1.8 = 2.1.2
# (Some version updates were missed here...)
# 2.0 = 2.3.1
# 2.1 = 2.3.2
# (Some version updates were missed here...)
# 2.2 = 2.6
# 2.3 = 2.7
# 2.4 = 2.9
# 2.5 = 2.10
# 2.6 = 2.11
# 2.7 = 2.12
# 2.8 = 2.13
# 2.9 = 2.14
# 3.1 = 3.1
# 3.2 = 3.2
_version=3.2
#
#
# Character set encoding used to read and write JMeter XML files and CSV results
#
_file_encoding=UTF-8
#
#---------------------------------------------------------
#
# The following properties are used to create aliases
# [Must all start with capital letter]
#
AccessLogSampler=org.apache.jmeter.protocol.http.sampler.AccessLogSampler
AjpSampler=org.apache.jmeter.protocol.http.sampler.AjpSampler
AjpSamplerGui=org.apache.jmeter.protocol.http.control.gui.AjpSamplerGui
AnchorModifier=org.apache.jmeter.protocol.http.modifier.AnchorModifier
AnchorModifierGui=org.apache.jmeter.protocol.http.modifier.gui.AnchorModifierGui
Argument=org.apache.jmeter.config.Argument
Arguments=org.apache.jmeter.config.Arguments
ArgumentsPanel=org.apache.jmeter.config.gui.ArgumentsPanel
AssertionGui=org.apache.jmeter.assertions.gui.AssertionGui
AssertionVisualizer=org.apache.jmeter.visualizers.AssertionVisualizer
AuthManager=org.apache.jmeter.protocol.http.control.AuthManager
Authorization=org.apache.jmeter.protocol.http.control.Authorization
AuthPanel=org.apache.jmeter.protocol.http.gui.AuthPanel
BackendListener=org.apache.jmeter.visualizers.backend.BackendListener
BackendListenerGui=org.apache.jmeter.visualizers.backend.BackendListenerGui
BeanShellAssertion=org.apache.jmeter.assertions.BeanShellAssertion
BeanShellAssertionGui=org.apache.jmeter.assertions.gui.BeanShellAssertionGui
BeanShellListener=org.apache.jmeter.visualizers.BeanShellListener
BeanShellPostProcessor=org.apache.jmeter.extractor.BeanShellPostProcessor
BeanShellPreProcessor=org.apache.jmeter.modifiers.BeanShellPreProcessor
BeanShellSampler=org.apache.jmeter.protocol.java.sampler.BeanShellSampler
BeanShellSamplerGui=org.apache.jmeter.protocol.java.control.gui.BeanShellSamplerGui
BeanShellTimer=org.apache.jmeter.timers.BeanShellTimer
BSFAssertion=org.apache.jmeter.assertions.BSFAssertion
BSFListener=org.apache.jmeter.visualizers.BSFListener
BSFPreProcessor=org.apache.jmeter.modifiers.BSFPreProcessor
BSFPostProcessor=org.apache.jmeter.extractor.BSFPostProcessor
BSFSampler=org.apache.jmeter.protocol.java.sampler.BSFSampler
BSFSamplerGui=org.apache.jmeter.protocol.java.control.gui.BSFSamplerGui
BSFTimer=org.apache.jmeter.timers.BSFTimer
CacheManager=org.apache.jmeter.protocol.http.control.CacheManager
CacheManagerGui=org.apache.jmeter.protocol.http.gui.CacheManagerGui
CompareAssertion=org.apache.jmeter.assertions.CompareAssertion
ComparisonVisualizer=org.apache.jmeter.visualizers.ComparisonVisualizer
ConfigTestElement=org.apache.jmeter.config.ConfigTestElement
ConstantThroughputTimer=org.apache.jmeter.timers.ConstantThroughputTimer
ConstantTimer=org.apache.jmeter.timers.ConstantTimer
ConstantTimerGui=org.apache.jmeter.timers.gui.ConstantTimerGui
Cookie=org.apache.jmeter.protocol.http.control.Cookie
CookieManager=org.apache.jmeter.protocol.http.control.CookieManager
CookiePanel=org.apache.jmeter.protocol.http.gui.CookiePanel
CounterConfig=org.apache.jmeter.modifiers.CounterConfig
CriticalSectionController=org.apache.jmeter.control.CriticalSectionController
CriticalSectionControllerGui=org.apache.jmeter.control.gui.CriticalSectionControllerGui
CounterConfigGui=org.apache.jmeter.modifiers.gui.CounterConfigGui
CSVDataSet=org.apache.jmeter.config.CSVDataSet
DebugPostProcessor=org.apache.jmeter.extractor.DebugPostProcessor
DebugSampler=org.apache.jmeter.sampler.DebugSampler
# removed in 3.1, class was deleted in r1763837
DistributionGraphVisualizer=org.apache.jmeter.visualizers.DistributionGraphVisualizer
DNSCacheManager=org.apache.jmeter.protocol.http.control.DNSCacheManager
DNSCachePanel=org.apache.jmeter.protocol.http.gui.DNSCachePanel
DurationAssertion=org.apache.jmeter.assertions.DurationAssertion
DurationAssertionGui=org.apache.jmeter.assertions.gui.DurationAssertionGui
# Should really have been defined as floatProp to agree with other properties
# No point changing this now
FloatProperty=org.apache.jmeter.testelement.property.FloatProperty
ForeachController=org.apache.jmeter.control.ForeachController
ForeachControlPanel=org.apache.jmeter.control.gui.ForeachControlPanel
FtpConfigGui=org.apache.jmeter.protocol.ftp.config.gui.FtpConfigGui
FTPSampler=org.apache.jmeter.protocol.ftp.sampler.FTPSampler
FtpTestSamplerGui=org.apache.jmeter.protocol.ftp.control.gui.FtpTestSamplerGui
GaussianRandomTimer=org.apache.jmeter.timers.GaussianRandomTimer
GaussianRandomTimerGui=org.apache.jmeter.timers.gui.GaussianRandomTimerGui
GenericController=org.apache.jmeter.control.GenericController
GraphAccumVisualizer=org.apache.jmeter.visualizers.GraphAccumVisualizer
GraphVisualizer=org.apache.jmeter.visualizers.GraphVisualizer
Header=org.apache.jmeter.protocol.http.control.Header
HeaderManager=org.apache.jmeter.protocol.http.control.HeaderManager
HeaderPanel=org.apache.jmeter.protocol.http.gui.HeaderPanel
HTMLAssertion=org.apache.jmeter.assertions.HTMLAssertion
HTMLAssertionGui=org.apache.jmeter.assertions.gui.HTMLAssertionGui
HTTPArgument=org.apache.jmeter.protocol.http.util.HTTPArgument
HTTPArgumentsPanel=org.apache.jmeter.protocol.http.gui.HTTPArgumentsPanel
HTTPFileArg=org.apache.jmeter.protocol.http.util.HTTPFileArg
HTTPFileArgs=org.apache.jmeter.protocol.http.util.HTTPFileArgs
HttpDefaultsGui=org.apache.jmeter.protocol.http.config.gui.HttpDefaultsGui
HtmlExtractor=org.apache.jmeter.extractor.HtmlExtractor
HtmlExtractorGui=org.apache.jmeter.extractor.gui.HtmlExtractorGui
# removed in r1039684, probably not released. Not present in r322831 or since.
#HttpGenericSampler=org.apache.jmeter.protocol.http.sampler.HttpGenericSampler
# removed in r1039684, probably not released. Not present in r322831 or since.
#HttpGenericSamplerGui=org.apache.jmeter.protocol.http.control.gui.HttpGenericSamplerGui
HttpMirrorControl=org.apache.jmeter.protocol.http.control.HttpMirrorControl
HttpMirrorControlGui=org.apache.jmeter.protocol.http.control.gui.HttpMirrorControlGui
# r397955 - removed test class. Keep as commented entry for info only.
#HTTPNullSampler=org.apache.jmeter.protocol.http.sampler.HTTPNullSampler
# Merge previous 2 HTTP samplers into one
HTTPSampler_=org.apache.jmeter.protocol.http.sampler.HTTPSampler
HTTPSampler2_=org.apache.jmeter.protocol.http.sampler.HTTPSampler2
HTTPSamplerProxy,HTTPSampler,HTTPSampler2=org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy
# Merge GUIs
HttpTestSampleGui,HttpTestSampleGui2=org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui
#HttpTestSampleGui2=org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui2
IfController=org.apache.jmeter.control.IfController
IfControllerPanel=org.apache.jmeter.control.gui.IfControllerPanel
IncludeController=org.apache.jmeter.control.IncludeController
IncludeControllerGui=org.apache.jmeter.control.gui.IncludeControllerGui
InterleaveControl=org.apache.jmeter.control.InterleaveControl
InterleaveControlGui=org.apache.jmeter.control.gui.InterleaveControlGui
JavaConfig=org.apache.jmeter.protocol.java.config.JavaConfig
JavaConfigGui=org.apache.jmeter.protocol.java.config.gui.JavaConfigGui
JavaSampler=org.apache.jmeter.protocol.java.sampler.JavaSampler
JavaTest=org.apache.jmeter.protocol.java.test.JavaTest
JavaTestSamplerGui=org.apache.jmeter.protocol.java.control.gui.JavaTestSamplerGui
JDBCDataSource=org.apache.jmeter.protocol.jdbc.config.DataSourceElement
JDBCPostProcessor=org.apache.jmeter.protocol.jdbc.processor.JDBCPostProcessor
JDBCPreProcessor=org.apache.jmeter.protocol.jdbc.processor.JDBCPreProcessor
JDBCSampler=org.apache.jmeter.protocol.jdbc.sampler.JDBCSampler
# Renamed to JMSSamplerGui; keep original entry for backwards compatibility
JMSConfigGui=org.apache.jmeter.protocol.jms.control.gui.JMSConfigGui
JMSProperties=org.apache.jmeter.protocol.jms.sampler.JMSProperties
JMSProperty=org.apache.jmeter.protocol.jms.sampler.JMSProperty
JMSPublisherGui=org.apache.jmeter.protocol.jms.control.gui.JMSPublisherGui
JMSSampler=org.apache.jmeter.protocol.jms.sampler.JMSSampler
JMSSamplerGui=org.apache.jmeter.protocol.jms.control.gui.JMSSamplerGui
JMSSubscriberGui=org.apache.jmeter.protocol.jms.control.gui.JMSSubscriberGui
JSONPostProcessor=org.apache.jmeter.extractor.json.jsonpath.JSONPostProcessor
JSONPostProcessorGui=org.apache.jmeter.extractor.json.jsonpath.gui.JSONPostProcessorGui
# Removed in r545311 as Jndi no longer present; keep for compat.
JndiDefaultsGui=org.apache.jmeter.protocol.jms.control.gui.JndiDefaultsGui
JSR223Assertion=org.apache.jmeter.assertions.JSR223Assertion
JSR223Listener=org.apache.jmeter.visualizers.JSR223Listener
JSR223PostProcessor=org.apache.jmeter.extractor.JSR223PostProcessor
JSR223PreProcessor=org.apache.jmeter.modifiers.JSR223PreProcessor
JSR223Sampler=org.apache.jmeter.protocol.java.sampler.JSR223Sampler
JSR223Timer=org.apache.jmeter.timers.JSR223Timer
JUnitSampler=org.apache.jmeter.protocol.java.sampler.JUnitSampler
JUnitTestSamplerGui=org.apache.jmeter.protocol.java.control.gui.JUnitTestSamplerGui
KeystoreConfig=org.apache.jmeter.config.KeystoreConfig
LDAPArgument=org.apache.jmeter.protocol.ldap.config.gui.LDAPArgument
LDAPArguments=org.apache.jmeter.protocol.ldap.config.gui.LDAPArguments
LDAPArgumentsPanel=org.apache.jmeter.protocol.ldap.config.gui.LDAPArgumentsPanel
LdapConfigGui=org.apache.jmeter.protocol.ldap.config.gui.LdapConfigGui
LdapExtConfigGui=org.apache.jmeter.protocol.ldap.config.gui.LdapExtConfigGui
LDAPExtSampler=org.apache.jmeter.protocol.ldap.sampler.LDAPExtSampler
LdapExtTestSamplerGui=org.apache.jmeter.protocol.ldap.control.gui.LdapExtTestSamplerGui
LDAPSampler=org.apache.jmeter.protocol.ldap.sampler.LDAPSampler
LdapTestSamplerGui=org.apache.jmeter.protocol.ldap.control.gui.LdapTestSamplerGui
LogicControllerGui=org.apache.jmeter.control.gui.LogicControllerGui
LoginConfig=org.apache.jmeter.config.LoginConfig
LoginConfigGui=org.apache.jmeter.config.gui.LoginConfigGui
LoopController=org.apache.jmeter.control.LoopController
LoopControlPanel=org.apache.jmeter.control.gui.LoopControlPanel
MailerModel=org.apache.jmeter.reporters.MailerModel
MailerResultCollector=org.apache.jmeter.reporters.MailerResultCollector
MailerVisualizer=org.apache.jmeter.visualizers.MailerVisualizer
MailReaderSampler=org.apache.jmeter.protocol.mail.sampler.MailReaderSampler
MailReaderSamplerGui=org.apache.jmeter.protocol.mail.sampler.gui.MailReaderSamplerGui
MD5HexAssertion=org.apache.jmeter.assertions.MD5HexAssertion
MD5HexAssertionGUI=org.apache.jmeter.assertions.gui.MD5HexAssertionGUI
ModuleController=org.apache.jmeter.control.ModuleController
ModuleControllerGui=org.apache.jmeter.control.gui.ModuleControllerGui
MongoScriptSampler=org.apache.jmeter.protocol.mongodb.sampler.MongoScriptSampler
MongoSourceElement=org.apache.jmeter.protocol.mongodb.config.MongoSourceElement
# removed in 3.2, class was deleted in r
MonitorHealthVisualizer=org.apache.jmeter.visualizers.MonitorHealthVisualizer
NamePanel=org.apache.jmeter.gui.NamePanel
ObsoleteGui=org.apache.jmeter.config.gui.ObsoleteGui
OnceOnlyController=org.apache.jmeter.control.OnceOnlyController
OnceOnlyControllerGui=org.apache.jmeter.control.gui.OnceOnlyControllerGui
# removed in 3.0, class was deleted in r1722962
ParamMask=org.apache.jmeter.protocol.http.modifier.ParamMask
# removed in 3.0, class was deleted in r1722757
ParamModifier=org.apache.jmeter.protocol.http.modifier.ParamModifier
# removed in 3.0, class was deleted in r1722757
ParamModifierGui=org.apache.jmeter.protocol.http.modifier.gui.ParamModifierGui
PoissonRandomTimer=org.apache.jmeter.timers.PoissonRandomTimer
PoissonRandomTimerGui=org.apache.jmeter.timers.gui.PoissonRandomTimerGui
PropertyControlGui=org.apache.jmeter.visualizers.PropertyControlGui
ProxyControl=org.apache.jmeter.protocol.http.proxy.ProxyControl
ProxyControlGui=org.apache.jmeter.protocol.http.proxy.gui.ProxyControlGui
PublisherSampler=org.apache.jmeter.protocol.jms.sampler.PublisherSampler
RandomControlGui=org.apache.jmeter.control.gui.RandomControlGui
RandomController=org.apache.jmeter.control.RandomController
RandomOrderController=org.apache.jmeter.control.RandomOrderController
RandomOrderControllerGui=org.apache.jmeter.control.gui.RandomOrderControllerGui
RandomVariableConfig=org.apache.jmeter.config.RandomVariableConfig
RecordController=org.apache.jmeter.protocol.http.control.gui.RecordController
RecordingController=org.apache.jmeter.protocol.http.control.RecordingController
# removed in r1039684, class was deleted in r580452
ReflectionThreadGroup=org.apache.jmeter.threads.ReflectionThreadGroup
RegexExtractor=org.apache.jmeter.extractor.RegexExtractor
RegexExtractorGui=org.apache.jmeter.extractor.gui.RegexExtractorGui
RegExUserParameters=org.apache.jmeter.protocol.http.modifier.RegExUserParameters
RegExUserParametersGui=org.apache.jmeter.protocol.http.modifier.gui.RegExUserParametersGui
RemoteListenerWrapper=org.apache.jmeter.samplers.RemoteListenerWrapper
RemoteSampleListenerWrapper=org.apache.jmeter.samplers.RemoteSampleListenerWrapper
RemoteTestListenerWrapper=org.apache.jmeter.samplers.RemoteTestListenerWrapper
RemoteThreadsListenerWrapper=org.apache.jmeter.threads.RemoteThreadsListenerWrapper
ResponseAssertion=org.apache.jmeter.assertions.ResponseAssertion
RespTimeGraphVisualizer=org.apache.jmeter.visualizers.RespTimeGraphVisualizer
ResultAction=org.apache.jmeter.reporters.ResultAction
ResultActionGui=org.apache.jmeter.reporters.gui.ResultActionGui
ResultCollector=org.apache.jmeter.reporters.ResultCollector
ResultSaver=org.apache.jmeter.reporters.ResultSaver
ResultSaverGui=org.apache.jmeter.reporters.gui.ResultSaverGui
RunTime=org.apache.jmeter.control.RunTime
RunTimeGui=org.apache.jmeter.control.gui.RunTimeGui
SampleSaveConfiguration=org.apache.jmeter.samplers.SampleSaveConfiguration
SampleTimeout=org.apache.jmeter.modifiers.SampleTimeout
SampleTimeoutGui=org.apache.jmeter.modifiers.gui.SampleTimeoutGui
SimpleConfigGui=org.apache.jmeter.config.gui.SimpleConfigGui
SimpleDataWriter=org.apache.jmeter.visualizers.SimpleDataWriter
SizeAssertion=org.apache.jmeter.assertions.SizeAssertion
SizeAssertionGui=org.apache.jmeter.assertions.gui.SizeAssertionGui
SMIMEAssertion=org.apache.jmeter.assertions.SMIMEAssertionTestElement
SMIMEAssertionGui=org.apache.jmeter.assertions.gui.SMIMEAssertionGui
SmtpSampler=org.apache.jmeter.protocol.smtp.sampler.SmtpSampler
SmtpSamplerGui=org.apache.jmeter.protocol.smtp.sampler.gui.SmtpSamplerGui
# removed in 3.2, class was deleted in r
SoapSampler=org.apache.jmeter.protocol.http.sampler.SoapSampler
# removed in 3.2, class was deleted in r
SoapSamplerGui=org.apache.jmeter.protocol.http.control.gui.SoapSamplerGui
# removed in 3.1, class was deleted in r1763837
SplineVisualizer=org.apache.jmeter.visualizers.SplineVisualizer
# Originally deleted in r397955 as class is obsolete; needed for compat.
SqlConfigGui=org.apache.jmeter.protocol.jdbc.config.gui.SqlConfigGui
StaticHost=org.apache.jmeter.protocol.http.control.StaticHost
StatGraphVisualizer=org.apache.jmeter.visualizers.StatGraphVisualizer
StatVisualizer=org.apache.jmeter.visualizers.StatVisualizer
SubscriberSampler=org.apache.jmeter.protocol.jms.sampler.SubscriberSampler
SubstitutionElement=org.apache.jmeter.assertions.SubstitutionElement
Summariser=org.apache.jmeter.reporters.Summariser
SummariserGui=org.apache.jmeter.reporters.gui.SummariserGui
SummaryReport=org.apache.jmeter.visualizers.SummaryReport
SwitchController=org.apache.jmeter.control.SwitchController
SwitchControllerGui=org.apache.jmeter.control.gui.SwitchControllerGui
SyncTimer=org.apache.jmeter.timers.SyncTimer
SystemSampler=org.apache.jmeter.protocol.system.SystemSampler
SystemSamplerGui=org.apache.jmeter.protocol.system.gui.SystemSamplerGui
TableVisualizer=org.apache.jmeter.visualizers.TableVisualizer
TCPConfigGui=org.apache.jmeter.protocol.tcp.config.gui.TCPConfigGui
TCPSampler=org.apache.jmeter.protocol.tcp.sampler.TCPSampler
TCPSamplerGui=org.apache.jmeter.protocol.tcp.control.gui.TCPSamplerGui
TestAction=org.apache.jmeter.sampler.TestAction
TestActionGui=org.apache.jmeter.sampler.gui.TestActionGui
TestBeanGUI=org.apache.jmeter.testbeans.gui.TestBeanGUI
TestFragmentController=org.apache.jmeter.control.TestFragmentController
TestFragmentControllerGui=org.apache.jmeter.control.gui.TestFragmentControllerGui
TestPlan=org.apache.jmeter.testelement.TestPlan
TestPlanGui=org.apache.jmeter.control.gui.TestPlanGui
ThreadGroup=org.apache.jmeter.threads.ThreadGroup
ThreadGroupGui=org.apache.jmeter.threads.gui.ThreadGroupGui
PostThreadGroup=org.apache.jmeter.threads.PostThreadGroup
PostThreadGroupGui=org.apache.jmeter.threads.gui.PostThreadGroupGui
SetupThreadGroup=org.apache.jmeter.threads.SetupThreadGroup
SetupThreadGroupGui=org.apache.jmeter.threads.gui.SetupThreadGroupGui
ThroughputController=org.apache.jmeter.control.ThroughputController
ThroughputControllerGui=org.apache.jmeter.control.gui.ThroughputControllerGui
TransactionController=org.apache.jmeter.control.TransactionController
TransactionControllerGui=org.apache.jmeter.control.gui.TransactionControllerGui
TransactionSampler=org.apache.jmeter.control.TransactionSampler
UniformRandomTimer=org.apache.jmeter.timers.UniformRandomTimer
UniformRandomTimerGui=org.apache.jmeter.timers.gui.UniformRandomTimerGui
URLRewritingModifier=org.apache.jmeter.protocol.http.modifier.URLRewritingModifier
URLRewritingModifierGui=org.apache.jmeter.protocol.http.modifier.gui.URLRewritingModifierGui
UserParameterModifier=org.apache.jmeter.protocol.http.modifier.UserParameterModifier
UserParameterModifierGui=org.apache.jmeter.protocol.http.modifier.gui.UserParameterModifierGui
UserParameters=org.apache.jmeter.modifiers.UserParameters
UserParametersGui=org.apache.jmeter.modifiers.gui.UserParametersGui
ViewResultsFullVisualizer=org.apache.jmeter.visualizers.ViewResultsFullVisualizer
# removed in 3.0, class was deleted in r1722757
WebServiceSampler=org.apache.jmeter.protocol.http.sampler.WebServiceSampler
# removed in 3.0, class was deleted in r1722757
WebServiceSamplerGui=org.apache.jmeter.protocol.http.control.gui.WebServiceSamplerGui
WhileController=org.apache.jmeter.control.WhileController
WhileControllerGui=org.apache.jmeter.control.gui.WhileControllerGui
WorkBench=org.apache.jmeter.testelement.WorkBench
WorkBenchGui=org.apache.jmeter.control.gui.WorkBenchGui
XMLAssertion=org.apache.jmeter.assertions.XMLAssertion
XMLAssertionGui=org.apache.jmeter.assertions.gui.XMLAssertionGui
XMLSchemaAssertion=org.apache.jmeter.assertions.XMLSchemaAssertion
XMLSchemaAssertionGUI=org.apache.jmeter.assertions.gui.XMLSchemaAssertionGUI
XPathAssertion=org.apache.jmeter.assertions.XPathAssertion
XPathAssertionGui=org.apache.jmeter.assertions.gui.XPathAssertionGui
XPathExtractor=org.apache.jmeter.extractor.XPathExtractor
XPathExtractorGui=org.apache.jmeter.extractor.gui.XPathExtractorGui
#
# Properties - all start with lower case letter and end with Prop
#
boolProp=org.apache.jmeter.testelement.property.BooleanProperty
collectionProp=org.apache.jmeter.testelement.property.CollectionProperty
doubleProp=org.apache.jmeter.testelement.property.DoubleProperty
elementProp=org.apache.jmeter.testelement.property.TestElementProperty
# see above - already defined as FloatProperty
#floatProp=org.apache.jmeter.testelement.property.FloatProperty
intProp=org.apache.jmeter.testelement.property.IntegerProperty
longProp=org.apache.jmeter.testelement.property.LongProperty
mapProp=org.apache.jmeter.testelement.property.MapProperty
objProp=org.apache.jmeter.testelement.property.ObjectProperty
stringProp=org.apache.jmeter.testelement.property.StringProperty
#
# Other - must start with a lower case letter (and not end with Prop)
# (otherwise they could clash with the initial set of aliases)
#
hashTree=org.apache.jorphan.collections.ListedHashTree
jmeterTestPlan=org.apache.jmeter.save.ScriptWrapper
sample=org.apache.jmeter.samplers.SampleResult
httpSample=org.apache.jmeter.protocol.http.sampler.HTTPSampleResult
statSample=org.apache.jmeter.samplers.StatisticalSampleResult
testResults=org.apache.jmeter.save.TestResultWrapper
assertionResult=org.apache.jmeter.assertions.AssertionResult
# removed in 3.2, class was deleted in r
monitorStats=org.apache.jmeter.visualizers.MonitorStats
sampleEvent=org.apache.jmeter.samplers.SampleEvent
#
# Converters to register. Must start line with '_'
# If the converter is a collection of subitems, set equal to "collection"
# If the converter needs to know the class mappings but is not a collection of
# subitems, set it equal to "mapping"
_org.apache.jmeter.protocol.http.sampler.HTTPSamplerBaseConverter=collection
_org.apache.jmeter.protocol.http.util.HTTPResultConverter=collection
_org.apache.jmeter.save.converters.BooleanPropertyConverter=
_org.apache.jmeter.save.converters.IntegerPropertyConverter=
_org.apache.jmeter.save.converters.LongPropertyConverter=
_org.apache.jmeter.save.converters.MultiPropertyConverter=collection
_org.apache.jmeter.save.converters.SampleEventConverter=
_org.apache.jmeter.save.converters.SampleResultConverter=collection
_org.apache.jmeter.save.converters.SampleSaveConfigurationConverter=collection
_org.apache.jmeter.save.converters.StringPropertyConverter=
_org.apache.jmeter.save.converters.HashTreeConverter=collection
_org.apache.jmeter.save.converters.TestElementConverter=collection
_org.apache.jmeter.save.converters.TestElementPropertyConverter=collection
_org.apache.jmeter.save.converters.TestResultWrapperConverter=collection
_org.apache.jmeter.save.ScriptWrapperConverter=mapping
#
# Remember to update the _version entry
#

View File

@ -0,0 +1,123 @@
# Class, property and value upgrade equivalences.
## Licensed to the Apache Software Foundation (ASF) under one or more
## contributor license agreements. See the NOTICE file distributed with
## this work for additional information regarding copyright ownership.
## The ASF licenses this file to You under the Apache License, Version 2.0
## (the "License"); you may not use this file except in compliance with
## the License. You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
#
# Format is as follows --
# for renamed test element & GUI classes:
# old.class.Name=new.class.Name
# old.class.Name|guiClassName=new.class.Name
# (e.g. for ConfigTestElement)
#
# for renamed / deleted properties:
# class.Name/Old.propertyName=newPropertyName
# if newPropertyName is omitted, then property is deleted
#
# for renamed values:
# old.class.Name.old.propertyName/oldValue=newValue
#
org.apache.jmeter.protocol.http.config.gui.UrlConfigGui=org.apache.jmeter.protocol.http.config.gui.HttpDefaultsGui
org.apache.jmeter.assertions.Assertion=org.apache.jmeter.assertions.ResponseAssertion
org.apache.jmeter.protocol.http.sampler.HTTPSamplerFull=org.apache.jmeter.protocol.http.sampler.HTTPSampler
org.apache.jmeter.control.gui.RecordController=org.apache.jmeter.protocol.http.control.gui.RecordController
org.apache.jmeter.timers.gui.ConstantThroughputTimerGui=org.apache.jmeter.testbeans.gui.TestBeanGUI
org.apache.jmeter.timers.ConstantThroughputTimer/ConstantThroughputTimer.throughput=throughput
org.apache.jmeter.protocol.jdbc.control.gui.JdbcTestSampleGui=org.apache.jmeter.testbeans.gui.TestBeanGUI
org.apache.jmeter.protocol.jdbc.sampler.JDBCSampler/JDBCSampler.query=query
#org.apache.jmeter.protocol.jdbc.sampler.JDBCSampler.JDBCSampler.dataSource/NULL=
# Convert DBconfig
org.apache.jmeter.protocol.jdbc.config.gui.DbConfigGui=org.apache.jmeter.testbeans.gui.TestBeanGUI
org.apache.jmeter.config.ConfigTestElement|org.apache.jmeter.protocol.jdbc.config.gui.DbConfigGui=org.apache.jmeter.protocol.jdbc.config.DataSourceElement
org.apache.jmeter.protocol.jdbc.config.DataSourceElement/JDBCSampler.url=dbUrl
org.apache.jmeter.protocol.jdbc.config.DataSourceElement/JDBCSampler.driver=driver
org.apache.jmeter.protocol.jdbc.config.DataSourceElement/JDBCSampler.query=query
org.apache.jmeter.protocol.jdbc.config.DataSourceElement/ConfigTestElement.username=username
org.apache.jmeter.protocol.jdbc.config.DataSourceElement/ConfigTestElement.password=password
# Convert PoolConfig
org.apache.jmeter.protocol.jdbc.config.gui.PoolConfigGui=org.apache.jmeter.testbeans.gui.TestBeanGUI
org.apache.jmeter.config.ConfigTestElement|org.apache.jmeter.protocol.jdbc.config.gui.PoolConfigGui=org.apache.jmeter.protocol.jdbc.config.DataSourceElement
org.apache.jmeter.protocol.jdbc.config.DataSourceElement/JDBCSampler.connections=
org.apache.jmeter.protocol.jdbc.config.DataSourceElement/JDBCSampler.connPoolClass=
org.apache.jmeter.protocol.jdbc.config.DataSourceElement/JDBCSampler.maxuse=poolMax
# SQL Config
org.apache.jmeter.config.ConfigTestElement/JDBCSampler.query=query
org.apache.jmeter.protocol.http.control.Header/TestElement.name=Header.name
# Upgrade AccessLogSampler
org.apache.jmeter.protocol.http.control.gui.AccessLogSamplerGui=org.apache.jmeter.testbeans.gui.TestBeanGUI
org.apache.jmeter.protocol.http.sampler.AccessLogSampler/AccessLogSampler.log_file=logFile
org.apache.jmeter.protocol.http.sampler.AccessLogSampler/HTTPSampler.port=portString
#Is the following used now?
#org.apache.jmeter.protocol.http.sampler.AccessLogSampler/AccessLogSampler.generator_class_name=
#Looks to be a new field
#filterClassName
org.apache.jmeter.protocol.http.sampler.AccessLogSampler/HTTPSampler.domain=domain
org.apache.jmeter.protocol.http.sampler.AccessLogSampler/AccessLogSampler.parser_class_name=parserClassName
org.apache.jmeter.protocol.http.sampler.AccessLogSampler/HTTPSampler.image_parser=imageParsing
# Renamed class
org.apache.jmeter.protocol.jms.control.gui.JMSConfigGui=org.apache.jmeter.protocol.jms.control.gui.JMSSamplerGui
# These classes have been deleted; there's no defined replacement
org.apache.jmeter.protocol.jdbc.config.gui.SqlConfigGui=org.apache.jmeter.config.gui.ObsoleteGui
org.apache.jmeter.protocol.jms.control.gui.JndiDefaultsGui=org.apache.jmeter.config.gui.ObsoleteGui
# Should probably map to something other than ObsoleteGui...
org.apache.jmeter.threads.ReflectionThreadGroup=org.apache.jmeter.config.gui.ObsoleteGui
# Convert BSFSamplerGui
org.apache.jmeter.protocol.java.control.gui.BSFSamplerGui=org.apache.jmeter.testbeans.gui.TestBeanGUI
org.apache.jmeter.protocol.java.sampler.BSFSampler/BSFSampler.filename=filename
org.apache.jmeter.protocol.java.sampler.BSFSampler/BSFSampler.language=scriptLanguage
org.apache.jmeter.protocol.java.sampler.BSFSampler/BSFSampler.parameters=parameters
org.apache.jmeter.protocol.java.sampler.BSFSampler/BSFSampler.query=script
# Obsolete Http user Parameters modifier test element
# Note: ConfigTestElement is the test element associated with ObsoleteGui
org.apache.jmeter.protocol.http.modifier.UserParameterModifier=org.apache.jmeter.config.ConfigTestElement
org.apache.jmeter.protocol.http.modifier.gui.UserParameterModifierGui=org.apache.jmeter.config.gui.ObsoleteGui
# Obsolete Graph Full Results listener
org.apache.jmeter.visualizers.GraphAccumVisualizer=org.apache.jmeter.config.gui.ObsoleteGui
# removed in 3.0, class was deleted in r1722757
org.apache.jmeter.protocol.http.sampler.WebServiceSampler=org.apache.jmeter.config.ConfigTestElement
# removed in 3.0, class was deleted in r1722757
org.apache.jmeter.protocol.http.control.gui.WebServiceSamplerGui=org.apache.jmeter.config.gui.ObsoleteGui
# removed in 3.0, class was deleted in r1722757
org.apache.jmeter.protocol.http.modifier.ParamModifier=org.apache.jmeter.config.ConfigTestElement
# removed in 3.0, class was deleted in r1722962
org.apache.jmeter.protocol.http.modifier.ParamMask=org.apache.jmeter.config.ConfigTestElement
# removed in 3.0, class was deleted in r1722757
org.apache.jmeter.protocol.http.modifier.gui.ParamModifierGui=org.apache.jmeter.config.gui.ObsoleteGui
# removed in 3.1, class was deleted in r1774947
org.apache.jmeter.visualizers.SplineVisualizer=org.apache.jmeter.config.gui.ObsoleteGui
# removed in 3.1 class was deleted in r1763837
org.apache.jmeter.visualizers.DistributionGraphVisualizer=org.apache.jmeter.config.gui.ObsoleteGui
# removed in 3.2 class was deleted in r1771608
org.apache.jmeter.visualizers.MonitorStats=org.apache.jmeter.config.ConfigTestElement
org.apache.jmeter.visualizers.MonitorHealthVisualizer=org.apache.jmeter.config.gui.ObsoleteGui
# removed in 3.2 class was deleted in r1783280
org.apache.jmeter.protocol.http.sampler.HTTPSampler2=org.apache.jmeter.config.ConfigTestElement
org.apache.jmeter.protocol.http.sampler.SoapSampler=org.apache.jmeter.config.ConfigTestElement
org.apache.jmeter.protocol.http.control.gui.SoapSamplerGui=org.apache.jmeter.config.gui.ObsoleteGui

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
This directory is expected by JMeter

View File

@ -0,0 +1 @@
This directory is expected by JMeter

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
<Properties>
<Property name="defaultLogLevel">info</Property>
</Properties>
<ThresholdFilter level="trace"/>
<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout
pattern="%highlight{%level{length=1} %date{HH:mm:ssZ} [%t] %c{2}.%method - %msg%n}{INFO=white,WARN=red,FATAL=bright red}"/>
</Console>
</Appenders>
<Loggers>
<Root level="${sys:defaultLogLevel}">
<AppenderRef ref="Console-Appender" level="${sys:defaultLogLevel}"/>
</Root>
</Loggers>
</Configuration>

View File

@ -0,0 +1 @@
server.rmi.localport=10101

View File

@ -0,0 +1 @@
server.rmi.localport=10102

View File

@ -0,0 +1 @@
server.rmi.localport=10103

View File

@ -0,0 +1 @@
server.rmi.localport=10104

View File

@ -0,0 +1 @@
server.rmi.localport=10100