diff --git a/tools/jmeter/build.gradle b/tools/jmeter/build.gradle index 0f43927b39..9b483ac9f2 100644 --- a/tools/jmeter/build.gradle +++ b/tools/jmeter/build.gradle @@ -31,6 +31,7 @@ dependencies { 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' @@ -43,6 +44,7 @@ task(runServer, dependsOn: 'classes', type: JavaExec) { "-s" ] } +// Just start ssh tunnels, without JMeter. task(runSsh, dependsOn: 'classes', type: JavaExec) { classpath = sourceSets.main.runtimeClasspath main = 'com.r3.corda.jmeter.Ssh' @@ -52,6 +54,12 @@ task(runSsh, dependsOn: 'classes', type: JavaExec) { 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 { systemProperty "search_paths", project(':tools:jmeter').configurations.runtime.files.join(";") systemProperty "java.rmi.server.hostname", "localhost" @@ -59,6 +67,9 @@ run { // 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("jmeterHosts") ) { args+= "-Xssh" args+= Eval.me(jmeterHosts) @@ -76,7 +87,7 @@ jar { } // For building a runnable jar with no other dependencies for remote JMeter slave server, that has Corda code on classpath. -// Run with: java -jar corda-jmeter-.jar +// Run with: java -jar jmeter-corda-.jar // No additional args required but will be passed if specified. task buildJMeterJAR(type: FatCapsule, dependsOn: 'jar') { applicationClass 'com.r3.corda.jmeter.Launcher' diff --git a/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/FlowSampler.kt b/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/BaseFlowSampler.kt similarity index 95% rename from tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/FlowSampler.kt rename to tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/BaseFlowSampler.kt index 206937da97..34b17e4901 100644 --- a/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/FlowSampler.kt +++ b/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/BaseFlowSampler.kt @@ -11,8 +11,10 @@ import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext import org.apache.jmeter.samplers.SampleResult - -abstract class FlowSampler() : AbstractJavaSamplerClient() { +/** + * 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", "", "The remote network address (hostname or IP address) to connect to for RPC.") val port = Argument("port", "10000", "", "The remote port to connect to for RPC.") diff --git a/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/Samplers.kt b/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/Samplers.kt index e5fc610e2f..e23cc399cc 100644 --- a/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/Samplers.kt +++ b/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/Samplers.kt @@ -9,8 +9,10 @@ import net.corda.finance.flows.CashIssueFlow import org.apache.jmeter.config.Argument import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext - -abstract class AbstractSampler : FlowSampler() { +/** + * 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 { @@ -26,6 +28,11 @@ abstract class AbstractSampler : FlowSampler() { } } +/** + * 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 = setOf(notary) diff --git a/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/Ssh.kt b/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/Ssh.kt index 3c4a38391a..93cc88cd7c 100644 --- a/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/Ssh.kt +++ b/tools/jmeter/src/main/kotlin/com/r3/corda/jmeter/Ssh.kt @@ -10,7 +10,9 @@ 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) @@ -28,7 +30,7 @@ class Ssh { 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() - // TODO: Where is this value used? Just on the remote agent to set up the RMI registry? + // 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). @@ -47,7 +49,6 @@ class Ssh { val session = connectToHost(jsch, remoteHost, userName) sessions += session - // TODO: maybe check the local host is actually "localhost"? // 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))