Setting up JMeter for Distributed testing in AWS with connectivity issues
I have to do distributed testing using JMeter. The objective is to have multiple remote servers in AWS controlled by one local server send a file download request to another server in AWS.
How can I set up the different servers in AWS?
How can I connect to them remotely?
Can someone provide some step by step instructions on how to do it?
I have tried several things but keep running into connectivity issues across networks.
Solution 1:
We had a similar task and we ran into a bunch of issues as well. Here are the details of the whole process and what we did to resolve the issues we encountered. Hope it helps.
We needed to send requests from 5 servers located in various regions of the world. So we launched 5 micro instances in AWS, each in a different region. We chose the regions to be as geographically apart as possible.
Remote (server) JMeters config
Here is how we set up each instance.
-
Installed java:
$ sudo apt-get update $ sudo apt-get install default-jre
-
Installed JMeter:
$ mkdir jmeter $ cd jmeter; $ wget ftp://apache.mirrors.pair.com//jmeter/binaries/apache-jmeter-2.9.tgz $ gunzip apache-jmeter-2.9.tgz;tar xvf apache-jmeter-2.9.tar
-
Edited the
jmeter.properties
file in the/bin
folder of the JMeter installation and uncomment the line containing theserver.rmi.localport
setting. We changed the port to 50000.server.rmi.localport=50000
-
Started JMeter server. Make sure the address and the port the server reports listening to are correct.
$ cd ~/jmeter/apache-jmeter-2.9/bin $ vi jmeter-server
Local (client) JMeter config
Then we set up JMeter to run tests remotely on these instances on our local client machine:
- Ensured to use the same version of JMeter as was running on the servers. Installed Java and JMeter as described above.
- Enabled remote testing by editing the
jmeter.properties
file that can be found in thebin
folder of the JMeter installation. The parameterremote_hosts
needed to be set with the public DNS of the remote servers we were connecting to. remote_hosts=54.x.x.x,54.x.x.x,54.x.x.x,54.x.x.x,54.x.x.x
We were now able to tell our client JMeter instance to run tests on any or all of our specified remote servers.
Issues and resolutions
Here are the issues we encountered and how we resolved them:
-
The client failed with:
ERROR - jmeter.engine.ClientJMeterEngine: java.rmi.ConnectException: Connection - refused to host: 127.0.0.1
It was due to the server host returning the private IP address as its address because of Amazon NAT. We fixed this by setting the parameter
RMI_HOST_DEF
that the/usr/local/jmeter/bin/jmeter-server
script includes in starting the server:RMI_HOST_DEF=-Djava.rmi.server.hostname=54.xx.xx.xx
Now, the AWS instance returned the server’s external IP, and we could start the test.
-
When the server node attempted to return the result and tried to connect to the client, the server tried to connect to the external IP address of my local machine. But it threw a connection refused error:
2013/05/16 12:23:37 ERROR - jmeter.samplers.RemoteListenerWrapper: testStarted(host) java.rmi.ConnectException: Connection refused to host: xxx.xxx.xxx.xx;
We resolved this issue by setting up reverse tunnels at the client side.
-
First, we edited the
jmeter.properties
file in the/bin
folder of the JMeter installation and uncommented the line containing theclient.rmi.localport
setting. We changed the port to 60000:client.rmi.localport=60000
-
Then we connected to each of the servers using SSH, and setup a reverse tunnel to port 60000 on the client.
$ ssh -i ~/.ssh/54-x-x-x.us-east.pem -R 60000:localhost:60000 [email protected]
We kept each of these sessions open, as the JMeter server needs to be able to deliver the test results to the client.
-
Then we set up the
JVM_ARGS
environment variable on the client, in thejmeter.sh
file in the/bin
folder:export JVM_ARGS="-Djava.rmi.server.hostname=localhost"
By doing this, JMeter will tell the servers to connect to
localhost:60000
for delivering their results. This ends up being tunneled back to the client. -
-
The SSH connections to the servers kept dropping after staying idle for a little bit. To prevent that from happening, we added a parameter to each of the SSH tunnel set up directing the client to wait 60 seconds before sending a null packet to the server to keep the connection alive:
$ ssh -i ~/.ssh/54-x-x-x.us-east.pem -o ServerAliveInterval=60 -R 60000:localhost:60000 [email protected]
(.ssh/config
version of all required SSH settings:
Host 54.x.x.x
HostName 54.x.x.x
Port 22
User ubuntu
ServerAliveInterval 60
RemoteForward 127.0.0.1:60000 127.0.0.1:60000
IdentityFile ~/.ssh/54-x-x-x.us-east.pem
IdentitiesOnly yes
Just use ssh 54.x.x.x
after setting this up.
)
Solution 2:
I just went though this on openstack and found the same issues... no idea why the jmeter remoting documentation only covers half the required steps. You can do it without tunnels or touching the properties files.
You need
- All nodes to advertise their public IP - on AWS/OS this defaults to the private IP
- Ingress rules for the RMI port which defaults to 1099 - I use this
- Ingress rules for the RMI "local" port which defaults to dynamic. Below I use 4001 for the client and 4000 for servers. The port can be the same but note the properties are different.
If you are using your workstation as the client you probably still need tunnels. Above Archana Aggarwal has good tips for tunnels.
Remote servers
Set java.rmi.server.hostname
and server.rmi.localport
inline or in the properties file.
jmeter-server -Djava.rmi.server.hostname=publicip -Dserver.rmi.localport=4000
Sneaky server on client
You can also run one on the same machine as the client. For clarity I've set java.rmi.server.hostname
but left server.rmi.localport
as dynamic
jmeter-server -Djava.rmi.server.hostname=localip
Client
Set java.rmi.server.hostname
and client.rmi.localport
inline or in the properties file. Use -R
etc like so:
jmeter -n -t Test.jmx -Rremotepublicip1,remotepublicip2 -Djava.rmi.server.hostname=clientpublicip -Dclient.rmi.localport=4001 -GmypropA=1 -GmypropB=2 -lresults.jtl