Alright, theory is great, but let us actually set this up. I will walk you through configuring distributed testing with JMeter from scratch. Think of this like assembling IKEA furniture -- it looks complicated until you follow the steps in order.
On each machine that will act as a worker (slave), you need to start the jmeter-server process. This is a long-running process that listens for incoming connections from the master.
# Navigate to JMeter bin directory on each worker machine
cd /opt/jmeter/bin
# Option 1: Start jmeter-server directly (Linux/Mac)
./jmeter-server
# Option 2: Start with specific RMI host (recommended for multi-NIC machines)
./jmeter-server -Djava.rmi.server.hostname=192.168.1.101
# Option 3: Start with custom port
./jmeter-server -Dserver.rmi.port=1099
# Option 4: Start with increased heap memory (for heavy tests)
JVM_ARGS="-Xms1g -Xmx4g" ./jmeter-server
# On Windows:
jmeter-server.batWhen jmeter-server starts successfully, you will see a message like: "Created remote object: UnicastServerRef2 [liveRef: [endpoint:[192.168.1.101:1099]..." This means the worker is ready and listening.
The master needs to know the IP addresses of all worker machines. You configure this in the jmeter.properties file.
# --- Distributed Testing Configuration ---
# List all worker machine IPs (comma-separated, no spaces)
remote_hosts=192.168.1.101,192.168.1.102,192.168.1.103
# If workers use non-default ports:
# remote_hosts=192.168.1.101:1099,192.168.1.102:1099,192.168.1.103:1099
# RMI port for the master (optional, useful for firewall rules)
server.rmi.port=1099
# Bind RMI to specific interface (for multi-NIC master machines)
# java.rmi.server.hostname=192.168.1.100
# Timeout for connecting to remote workers (ms)
# Default is 20000 (20 seconds)
remote.connect.timeout=30000
# Timeout for waiting for worker response (ms)
remote.response.timeout=60000
# Continue test if one worker fails to connect
remote.continue_on_fail=falseThis is where most setups fail. JMeter RMI uses multiple ports, and if your firewall blocks any of them, the test will not work. Let me break down exactly what needs to be open.
| Port | Direction | Purpose | Configured Where |
|---|---|---|---|
| 1099 (default) | Master -> Worker | RMI Registry -- initial connection and test plan distribution | server.rmi.port in jmeter.properties |
| 1099 (default) | Worker -> Master | Results sent back from worker to master | server.rmi.port in jmeter.properties |
| Dynamic (random) | Both directions | RMI data transfer -- can be pinned to a fixed port | server.rmi.localport in jmeter.properties |
| 4000-4002 (if SSL) | Both directions | RMI over SSL uses additional ports for secure channel | See SSL section below |
# On worker machines: allow incoming on RMI port from master
sudo iptables -A INPUT -p tcp --dport 1099 -s 192.168.1.100 -j ACCEPT
# On master machine: allow incoming on RMI port from all workers
sudo iptables -A INPUT -p tcp --dport 1099 -s 192.168.1.101 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 1099 -s 192.168.1.102 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 1099 -s 192.168.1.103 -j ACCEPT
# Pin RMI data port to avoid dynamic port issues
# Add to jmeter.properties on ALL machines:
# server.rmi.localport=4000
# Then open port 4000 in firewall too
sudo iptables -A INPUT -p tcp --dport 4000 -s 192.168.1.0/24 -j ACCEPTPin your RMI data port by adding server.rmi.localport=4000 to jmeter.properties on every machine. This avoids the "random port" problem where RMI picks a different port each time, making firewall rules impossible to maintain.
Starting from JMeter 4.0, RMI communication between master and workers uses SSL by default. This is great for security but adds setup complexity. You have two choices: configure SSL properly (recommended for production) or disable it (acceptable for isolated test environments).
# JMeter includes a script to create the RMI keystore
# Run this on EVERY machine (master + all workers)
cd /opt/jmeter/bin
# This creates rmi_keystore.jks in the bin directory
./create-rmi-keystore.sh
# Follow the prompts:
# - Enter keystore password (default: changeit)
# - Enter key password (same as keystore password)
# - Enter validity days (365 is fine for testing)
# The generated rmi_keystore.jks must be identical on ALL machines
# Best practice: generate once, copy to all machines
scp rmi_keystore.jks user@worker1:/opt/jmeter/bin/
scp rmi_keystore.jks user@worker2:/opt/jmeter/bin/
scp rmi_keystore.jks user@worker3:/opt/jmeter/bin/# Add to jmeter.properties on ALL machines (master + workers)
server.rmi.ssl.disable=true
# WARNING: Only use this in isolated test environments
# Never disable SSL when testing over public networksIf SSL is enabled on the master but disabled on a worker (or vice versa), you will get a cryptic SSLHandshakeException. The SSL setting must be consistent across ALL machines. Either everyone has SSL enabled with the same keystore, or everyone has it disabled.
Remember, JMeter only sends the JMX file. Everything else must be pre-deployed.
Copy CSV data files to the same path on every worker (use absolute paths in your test plan, or put CSVs in the JMeter bin directory)
Install any custom JMeter plugins (JAR files) in the lib/ext directory on every worker
Copy any external BeanShell or Groovy scripts to the same path on every worker
If using SSL client certificates for the target app, deploy keystores to every worker
Verify Java and JMeter versions match across all machines: java -version and jmeter --version
Test network connectivity from every worker to the target application: curl http://target-app:8080/health
Automate resource deployment with a simple shell script or Ansible playbook. In real projects, you will be setting up and tearing down workers frequently, and manually copying files to 10 machines every time is a recipe for mistakes.
Q: Walk me through how you would set up JMeter distributed testing for a project that needs to simulate 10,000 concurrent users.
A: First, I would determine the number of workers needed. Assuming 1,000-1,500 users per machine, I would provision 8-10 worker machines plus one master. All machines would run the same JMeter and Java version. On each worker, I would start jmeter-server with adequate heap memory (JVM_ARGS="-Xmx4g" ./jmeter-server). On the master, I would configure remote_hosts in jmeter.properties with all worker IPs. I would set server.rmi.localport to a fixed value (e.g., 4000) on all machines to simplify firewall rules. For SSL, I would generate an RMI keystore once and distribute it to all machines. Then I would deploy CSV data files and any plugins to every worker at identical paths. I would set the thread count in my JMX to 1,000-1,250 (10,000 divided by 8-10 workers). Finally, I would run a smoke test with 10 threads per worker to verify connectivity before the full load run.
Key Point: Setup requires identical JMeter/Java versions, jmeter-server on workers, remote_hosts on master, firewall rules for RMI ports, consistent SSL config, and pre-deployed test resources.