- Amazon (https://aws.amazon.com/free/)
- DigitalOcean (https://www.digitalocean.com/join/)
- JMeter Server (https://hub.docker.com/r/hhcordero/docker-jmeter-server) aka "Slave"
- JMeter Client Non-gui (https://hub.docker.com/r/hhcordero/docker-jmeter-client) aka "Master"
-
Docker and Docker-Machine cli installed on your host (https://docs.docker.com/installation/)
-
You can choose either Amazon or DigitalOcean
Amazon:
- Access Key
- Secret Key
- Region
- VPC ID
- Subnet ID
- Zone
- AMI
DigitalOcean:
- Access Token
-
JMeter test plan on your host (http://jmeter.apache.org/usermanual/build-web-test-plan.html)
-
Provision machine for JMeter Master (Non-gui mode)
For AWS:
$ ./launch_jmeter_master_aws
For DigitalOcean:
$ ./launch_jmeter_master_do
For local machine:
$ ./launch_jmeter_master_local
-
Provision machine for JMeter Slave (Server mode)
Optional parameter - indicate number of servers to provision, value between 1 to 20. Default to 1 if no parameter is given.
For AWS:
$ ./launch_jmeter_slave_aws 2
For DigitalOcean:
$ ./launch_jmeter_slave_do 2
-
Copy test plan (jmx file) to jmeter-master machine inside /load_tests
Connect to jmeter-master machine and create /load_tests directory
$ eval "$(docker-machine env --swarm jmeter-master)" $ docker-machine ssh jmeter-master
For AWS:
$ sudo mkdir /load_tests && sudo chown ubuntu:ubuntu /load_tests
For DigitalOcean:
$ mkdir /load_tests
For local machine:
$ sudo mkdir /load_tests && sudo chown docker:docker /load_tests
Then go back to host
$ exit
Copy test plan from host to jmeter-master machine
Syntax:
docker-machine scp [path to test directory] [machine name]:/load_tests
Example:
$ docker-machine scp -r /home/user/docker-jmeter-master/load_tests/my_test jmeter-master:/load_tests
Then go back to host
$ exit
-
Run JMeter load test - execute the following commands, replace values if necessary before executing
Get JMeter master machine ip
$ IP=$(docker-machine ip jmeter-master)
Replace the value with the output from ./launch_jmeter_slave - must be comma separated jmeter slave ip addresses
$ REMOTE_HOSTS=""
Parent directory for the test plan
$ TEST_DIR="my_test"
Test plan without file extension
$ TEST_PLAN="test-plan"
Run the JMeter master non-gui and perform load test
$ docker run \ --detach \ --publish 1099:1099 \ --volume /load_tests/$TEST_DIR:/load_tests/$TEST_DIR \ --env TEST_DIR=$TEST_DIR \ --env TEST_PLAN=$TEST_PLAN \ --env IP=$IP \ --env REMOTE_HOSTS=$REMOTE_HOSTS \ --env constraint:type==master \ hhcordero/docker-jmeter-client
To monitor output, follow the logs:
Syntax:
docker logs -f [container name]
Example:
$ docker logs -f jmeter-master/tender_feynman
-
Save the result, look for the .jtl file inside jmeter-master /load_tests/$TEST_DIR
Syntax:
docker-machine scp [machine name]:/load_tests/[test dir]/[test plan result] [path to test directory]
Example:
$ docker-machine scp jmeter-master:/load_tests/${TEST_DIR}/${TEST_PLAN}.jtl /home/user/docker-jmeter-master/load_tests/my_test/.
Excellent project, nice work. When starting the client containers (and executing the test), I seem to be having issues with the server and client nodes communicating. Does an SSH tunnel need to be configured between these machines?
016/05/31 20:48:02 INFO - jmeter.engine.DistributedRunner: Configuring remote engine: 54.xxx.yyy.zzz 2016/05/31 20:50:09 ERROR - jmeter.engine.DistributedRunner: Failed to create engine at 54.xxx.yyy.zzz java.rmi.ConnectException: Connection refused to host: 54.xxx.yyy.zzz; nested exception is: java.net.ConnectException: Operation timed out at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619) at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216) at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202) at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:341) at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source) at java.rmi.Naming.lookup(Naming.java:101) at org.apache.jmeter.engine.ClientJMeterEngine.getEngine(ClientJMeterEngine.java:54) at org.apache.jmeter.engine.ClientJMeterEngine.<init>(ClientJMeterEngine.java:67) at org.apache.jmeter.engine.DistributedRunner.createEngine(DistributedRunner.java:237) at org.apache.jmeter.engine.DistributedRunner.getClientEngine(DistributedRunner.java:213) at org.apache.jmeter.engine.DistributedRunner.init(DistributedRunner.java:91) at org.apache.jmeter.JMeter.runNonGui(JMeter.java:814) at org.apache.jmeter.JMeter.startNonGui(JMeter.java:737) at org.apache.jmeter.JMeter.start(JMeter.java:395) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.jmeter.NewDriver.main(NewDriver.java:264) Caused by: java.net.ConnectException: Operation timed out at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:579) at java.net.Socket.connect(Socket.java:528) at java.net.Socket.<init>(Socket.java:425) at java.net.Socket.<init>(Socket.java:208) at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40) at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:147) at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613) ... 18 more