Scale JMeter with distributed testing: controller and workers, RMI SSL, ports, -R CLI, data files on each engine, and result aggregation pitfalls.
JMeter Distributed Testing Guide
Section titled “JMeter Distributed Testing Guide”When a single injector cannot generate enough load - or is limited by network or CPU - JMeter can drive multiple remote engines from one client. This guide explains the controller-worker model, setup steps, CLI usage, SSL/RMI, data files, result collection, limits, and troubleshooting, grounded in the official Remote Testing manual and the step-by-step tutorial.
How distributed testing works
Section titled “How distributed testing works”JMeter uses a controller (client) + workers (servers) architecture (historically called master/slave):
| Role | Responsibility |
|---|---|
| Controller / client | Holds the test plan start command, sends the plan to workers, starts/stops the test, collects sample results, writes the combined result file locally |
| Worker / server | Runs jmeter-server, executes the full test plan, streams results back |
Documented features of remote mode:
- Saving of test samples to the local (controller) machine
- Management of multiple JMeter engines from one machine
- No need to copy the test plan to each server - the client sends it
Critical load math
Section titled “Critical load math”From the official remote testing chapter:
The same test plan is run by all the servers. JMeter does not distribute the load between servers; each runs the full test plan. So if you set 1000 Threads and have 6 JMeter servers, you end up injecting 6000 Threads.
Plan thread counts per worker, not as a global pool that JMeter will shard for you.
When not to use remote mode
Section titled “When not to use remote mode”The manual notes that remote mode uses more resources than running the same number of independent CLI tests. With many servers, the client and its network can become overloaded even though workers still run. Always verify the controller is healthy.
Also: do not run the JMeter engine on the application server under test if you can avoid it - the engine steals CPU and taints results. Prefer injectors on the same Ethernet segment as the app tier without sharing the app hosts.
Prerequisites (all nodes)
Section titled “Prerequisites (all nodes)”Official checklist - every client and server must:
- Run exactly the same version of JMeter.
- Use the same Java version on all systems (mixed versions may work but are discouraged).
- Have a valid keystore for RMI over SSL, or SSL explicitly disabled in a controlled lab.
- Be reachable on the RMI ports you configure (firewalls allowing client→server and reverse result channels).
Data files are not auto-copied
Section titled “Data files are not auto-copied”If the plan uses CSV files, plugins JARs, or other external resources:
these are not sent across by the client - make sure they are available in the appropriate directory on each server.
You may use different user.properties / system.properties per server (for example unique data partitions or different backend targets). Properties are picked up when the server starts.
Network and ports
Section titled “Network and ports”| Direction | Purpose | Notes from docs |
|---|---|---|
| Client → server | Control / RMI | Default registry port 1099 (typical) |
| Server → client | Sample results | High-numbered ports; control with client.rmi.localport base |
| Server local engine port | RMI engine | Dynamic by default; set server.rmi.localport for firewall-friendly fixed ports |
If firewalls exist between client and servers, allow the chosen ports both ways as required for RMI. The manual suggests monitoring traffic if connections fail.
There can be only one JMeter server per node unless you use different RMI ports.
Step-by-step setup
Section titled “Step-by-step setup”Follow the Distributed Testing Step-by-Step tutorial for screenshots, or the full Remote Testing reference.
Step 0 - Configure nodes
Section titled “Step 0 - Configure nodes”- Identical JMeter + Java
- SSL keystore distributed or intentional SSL disable for lab only
- CSV/plugin files present on workers
- Optional: set
server.rmi.localporton servers for fixed ports
Step 1 - Start workers
Section titled “Step 1 - Start workers”On each worker machine:
# Unixjmeter-server
# Windowsjmeter-server.batThe server application starts the RMI registry itself; you normally do not start rmiregistry separately. (Older manual mode with server.rmi.create=false exists for special cases - see remote testing “Doing it Manually”.)
Optional: server.exitaftertest=true so the server exits after one test. The client -X flag also requests remote servers to exit at end of test.
Step 2 - Point the client at workers
Section titled “Step 2 - Point the client at workers”Option A - properties file on the controller: set remote_hosts in jmeter.properties / overrides to a comma-separated list of worker hosts.
Option B - CLI (preferred for automation):
jmeter -n -t script.jmx -R host1,host2,host3 -l results.jtlDocumented equivalence: -R has the same effect as using -r with -Jremote_hosts={serverlist}.
jmeter -n -t script.jmx -ruses whatever is already in remote_hosts.
Step 3a - GUI check (debug only)
Section titled “Step 3a - GUI check (debug only)”Start the controller GUI; Run menu includes Remote Start / Remote Stop for configured hosts. Use this only to validate connectivity - not for real load.
Step 3b - CLI client (recommended)
Section titled “Step 3b - CLI client (recommended)”jmeter -n -t script.jmx -R server1,server2 -l results.jtl -e -o report/Useful flags from the manual:
| Flag | Meaning |
|---|---|
-Gproperty=value | Define a property on all servers (repeatable) |
-X | Exit remote servers at the end of the test |
-Jproperty=value | Property on the client (and as usual for plan \${__P}) |
The command-line client exits when remote servers have stopped.
SSL for RMI (default since JMeter 4.0)
Section titled “SSL for RMI (default since JMeter 4.0)”Since JMeter 4.0 the default RMI transport uses SSL. You must create keys/certificates.
JMeter ships:
bin/create-rmi-keystore.shbin/create-rmi-keystore.bat
Run from bin; the script generates a keystore with a key named rmi (default alias), valid seven days in the documented sample flow, default passphrase changeit. Answer the keytool prompts (CN should align with alias expectations; docs show using rmi as the name).
Then:
- Ensure
rmi_keystore.jksis injmeter/binor referenced byserver.rmi.ssl.keystore.file. - Copy the same keystore to every server and client in the farm.
Default RMI SSL-related properties are described under the properties reference remote section.
Lab-only SSL disable
Section titled “Lab-only SSL disable”Some teams temporarily set server.rmi.ssl.disable=true in user.properties on all nodes for isolated labs. Treat that as non-production only; prefer proper keystores for any shared or long-lived environment.
What the controller aggregates
Section titled “What the controller aggregates”Workers execute samples; results stream back so the controller can:
- Write a combined result file (
-l) - Drive listeners in GUI (not recommended under load)
- Produce one HTML dashboard from the combined log
The dashboard docs note a limitation on the “times vs threads” graph in distributed mode (axis reflects threads for one server - see generating-dashboard notes).
Stripped modes
Section titled “Stripped modes”The remote testing manual mentions improvements via Stripped sample sending modes to reduce client overload. Prefer current defaults for your version, and still watch controller CPU, disk, and network when many workers send high-rate results.
Sizing workers and threads
Section titled “Sizing workers and threads”- Decide total target concurrency or RPS.
- Decide how many injectors you have.
- Set Thread Group threads ≈ total / workers (plus headroom), remembering each worker runs the full group.
- Size heap per worker for its local thread count (Heap Estimator).
- Size the controller for result aggregation, not only for zero local threads.
- Use the Thread Calculator for per-engine starting points; validate with pilots.
Best practices also allow multiple autonomous CLI instances without remote mode: run N independent jmeter -n processes and merge sample result files later for analysis. That avoids RMI complexity when you do not need centralized start/stop.
Properties that commonly matter
Section titled “Properties that commonly matter”Configure overrides in user.properties (recommended pattern: copy from jmeter.properties, do not edit only the stock file long-term):
| Area | Examples (see properties reference for exact names) |
|---|---|
| Host list | remote_hosts |
| Server RMI port | server.rmi.localport |
| Client reverse ports | client.rmi.localport |
| SSL keystore | server.rmi.ssl.keystore.file, alias, password props |
| SSL disable | server.rmi.ssl.disable (lab) |
| Exit after test | server.exitaftertest |
Unsure which knobs matter? Use the Properties Cheat Sheet and the full Properties Reference.
Operational runbook
Section titled “Operational runbook”Healthy start order
Section titled “Healthy start order”- Deploy identical JMeter/Java to all nodes.
- Deploy keystore + data files to workers.
- Start
jmeter-serveron each worker; confirm logs show RMI up. - From controller, start CLI with
-Rand a small thread count. - Confirm samples arrive in the result file.
- Scale threads/workers gradually.
During the test
Section titled “During the test”- Watch worker CPU, network, GC.
- Watch controller disk I/O for the JTL.
- Prefer Backend Listener for live metrics if you need dashboards mid-test.
- Avoid View Results Tree on the controller under load.
After the test
Section titled “After the test”- Generate dashboard from the controller’s result file.
- Use
-Xorserver.exitaftertestif you want workers to shut down. - Collect
jmeter-serverlogs from workers if anything failed.
Troubleshooting
Section titled “Troubleshooting”| Problem | What to check |
|---|---|
| Connection refused | jmeter-server running? host/IP correct? firewall on 1099 / server.rmi.localport? |
| Workers not listed / not starting | remote_hosts / -R list; DNS resolution; ping/route |
| Serialization / class errors | Identical JMeter versions; same plugins on all nodes |
| SSL handshake failures | Keystore present on all nodes; alias/password; clocks; or lab SSL disable consistently |
| No samples / incomplete results | Reverse ports blocked (client.rmi.localport range); client overloaded |
| Different behaviour per worker | Missing CSV on some nodes; different user.properties |
| Controller overloaded | Too many workers/high sample rate; use stripped modes; fewer result fields; autonomous CLI merge strategy |
| “Unknown host” / wrong interface | Bind addresses, multi-homed hosts, VPN interfaces |
Debugging tips from the manual include RMI-related system properties for verbose RMI logs when diagnosing refused connections.
Distributed testing vs alternatives
Section titled “Distributed testing vs alternatives”| Approach | Pros | Cons |
|---|---|---|
Remote mode (-R) | One start/stop; combined results; plan pushed to workers | RMI/SSL complexity; client bottleneck |
| Independent CLI engines | Simple; no RMI | Manual start; merge JTLs yourself |
| Single powerful injector | Simplest | Hardware/network ceiling |
| CI single container | Easy automation | Limited scale (CI guide) |
Choose remote mode when you need central coordination and many injectors; choose autonomous CLIs when you want operational simplicity.
Security checklist
Section titled “Security checklist”- Trusted network or strict firewall allowlists only.
- SSL keystores with controlled distribution; rotate when using short-lived certs (documented sample validity is short - regenerate for real use).
- No
jmeter-serverexposed to the public internet. - Test plans treated as code - remote start executes what the client sends.
- Disable experimental SSL-off settings outside labs.
Result file and sample sending behaviour
Section titled “Result file and sample sending behaviour”Under load, workers generate samples quickly. The controller must:
- Receive sample events over RMI.
- Write them to the local result file if
-lis set. - Optionally feed listeners or Backend Listener exporters.
That is why the remote testing chapter warns that the client can become the bottleneck. Mitigations aligned with official guidance and lean-run practice:
- Prefer CLI controller with listeners disabled.
- Save only required fields (
jmeter.save.saveservice.*) so each sample is smaller. - Prefer CSV over XML results.
- Avoid functional mode and full response data on every sample.
- Use current stripped sample sending modes when available for your version.
- Cap how many workers report to one controller; split farms if needed.
- Consider autonomous CLI engines plus offline merge when coordination is not required.
If you need live charts without overloading the controller GUI, use the Backend Listener path so metrics stream to InfluxDB/Grafana from the engines or controller according to your plan design - still validate that the extra exporter CPU is acceptable.
Example lab topology
Section titled “Example lab topology”A minimal two-worker lab that matches the docs:
| Host | Role | Software |
|---|---|---|
controller.lab | Client | Same JMeter + Java; has .jmx; runs CLI |
worker1.lab | Server | Same JMeter + Java; jmeter-server; CSV data present |
worker2.lab | Server | Same as worker1 |
# on each workercd $JMETER_HOME/bin./jmeter-server
# on controller./jmeter -n -t /plans/api.jmx \ -R worker1.lab,worker2.lab \ -Jthreads=50 \ -Ghost=app.lab \ -l /tmp/results.jtl \ -e -o /tmp/report \ -XIf the plan uses \${__P(threads,)} for the Thread Group, remember: each worker applies that property independently. -Jthreads=50 sets the client property; workers need the same value via -Gthreads=50 if they evaluate __P for thread count when the engine starts the plan. Match where the property is read - when in doubt, bake conservative defaults into the plan and override consistently with -G for remote engines.
Checklist before first production-scale distributed run
Section titled “Checklist before first production-scale distributed run”- Versions identical (JMeter + Java) on all nodes.
- Keystore distributed; SSL smoke-tested.
- Firewall rules include control and reverse ports.
- CSV, keystores for the app under test, and plugin JARs on every worker.
- Small pilot with 1-2 threads per worker succeeds end-to-end.
- Controller disk has space for the full combined JTL.
- Heap sized per worker for planned local threads.
- Runbook includes who starts workers, who starts the client, and how to stop (
shutdown/stopscripts or remote stop). - Success criteria defined (error %, latency) before you stare at six worker CPU graphs.
- Rollback: how to halt generation if the app tier melts down.
Related documentation
Section titled “Related documentation”- Remote Testing (full reference)
- Distributed Testing Step-by-Step
- Properties Reference
- Best Practices - multi-machine CLI
- Dashboard Report
- Real-time Results
Frequently asked questions
Section titled “Frequently asked questions”Does JMeter split 1000 threads across 4 workers?
Section titled “Does JMeter split 1000 threads across 4 workers?”No. Each worker runs the full test plan. Four workers with 1000 threads configured means about 4000 threads total.
Do I need to copy the JMX to every worker?
Section titled “Do I need to copy the JMX to every worker?”No. The client sends the test plan to the servers. You do need to copy external data files and ensure plugins match.
GUI or CLI for distributed load?
Section titled “GUI or CLI for distributed load?”CLI. The manual recommends starting remote tests from a non-GUI client for real load; GUI is for checking configuration.
What is the default RMI port?
Section titled “What is the default RMI port?”JMeter/RMI commonly uses 1099 for the server registry connection; result channels use additional ports. Fix ports with server.rmi.localport and client.rmi.localport when firewalls require it.
Why did SSL start matter after JMeter 4.0?
Section titled “Why did SSL start matter after JMeter 4.0?”Since JMeter 4.0, default RMI transport uses SSL and needs a keystore. Use create-rmi-keystore scripts and distribute rmi_keystore.jks.
Can workers run different Java versions?
Section titled “Can workers run different Java versions?”It may work but is discouraged. Use the same Java and JMeter versions everywhere.
Is distributed mode always better than one machine?
Section titled “Is distributed mode always better than one machine?”No. Remote mode adds overhead and can overload the client. Sometimes one large injector or several independent CLI runs is simpler and more reliable.
On this page
On this page
- Overview
- How distributed testing works
- Prerequisites (all nodes)
- Network and ports
- Step-by-step setup
- SSL for RMI (default since JMeter 4.0)
- What the controller aggregates
- Sizing workers and threads
- Properties that commonly matter
- Operational runbook
- Troubleshooting
- Distributed testing vs alternatives
- Security checklist
- Result file and sample sending behaviour
- Example lab topology
- Checklist before first production-scale distributed run
- Related documentation
- Frequently asked questions