JMeter – How To Share Data In Distributed Load Testing

In this article, I would like to show how we can share data among all the JMeter servers in distributed mode.

Problem Statement:

asm003If you have been running JMeter in distributed mode, you might already know that setting up all the JMeter servers with all the dependency is a pain. We already see that docker greatly simplifies the JMeter master and slave setup.

If you have not checked these articles out already, I would suggest you check these first.

However, JMeter master simply runs the .jmx file in all the server machines. If the JMeter test is depending on test data in a CSV file, then you need to copy the CSV file and distribute yourself to all the JMeter servers. Most of the times, test data used by Slave1 can not be used by other slaves. We also need to ensure that you split the CSV file and distribute to the slaves. Unfortunately docker can not help us here directly with the test data distribution.

 CSV in Distributed Mode:

Even if we split the file and moved to the slaves by using a script, still there is a limitation with this approach.

Lets assume, We have 10,000 records to process and we have 4 slaves. So we split the 10K record CSV file into 4 CSV files with 2500 records each. If the JMeter test is supposed to process all the records, there is a chance that some slaves might have finished the test sooner than others. It happens because each row does not necessarily have to take same amount of time to process by the application under test. So when one of the servers is still processing its 2400th record, another server could have completed all the 2500 records.

jm-redis-01

In the above setup, after some time, we might see some servers have finished the test – while other servers still working very hard to finish the test. Even though these servers are available to help the other servers which are still running, they can not as they do not have the test data.

  • Pros

    • Fast
  • Cons

    • The huge data file has to be split into multiple files based on the number of servers we use.
    • File has to be moved to all the slaves either manually / using custom scripts.
    • Each server has its own data. Data sharing among them is not possible.
    • Once the test is started,  We can not add more data for the slaves.

 

What is Redis:

Redis stands for REmote DIctionary Server. It is an open source in-memory data structure store database. It stores various data structures like String, Map, Lists, Sets etc as Key value pairs. As it is an in-memory database, It keeps all the data in the RAM (but it can also write the data in the disk periodically). So you get significant amount of performance boost while reading/writing the data.

ReDis in Distributed Mode:

Instead of keeping all the test data in a CSV file, splitting them and distribute them – We will move all data to Redis DB and Redis will be serving the test data to the JMeter servers.  The set up will be as shown here.

jm-redis-02

If you would like to use Redis instead of CSV, you do NOT have to change a lot in your JMeter test. You just need to use “jp@gc – Redis Data Set” plugin and update the Redis DB server details in the JMeter test plan. We will be using the same variable names, your JMeter test would not really know who is serving the test data. The test will run just fine.

jm-redis-03

We can also add more data to the ReDis server while JMeter slaves are running the test.

  • Pros

    • Data sharing among the slaves are very easy. No need to split the files.
    • Redis serves the data to all the servers. So no need to worry moving the test data to the servers.
    • Load is distributed evenly among the servers.
    • New data can be added to the ReDis server to serve for the JMeter slaves while the test is running.
  • Cons

    • Relatively slow [This slowness is not because of ReDis. It could be due to your network].

JMeter-ReDis Infrastructure Setup:

Lets create a docker compose file for our complete JMeter-Redis test infrastructure as shown below. [I assume you already have some idea about docker-compose. If not, Please check this article]

  • Create a directory.

mkdir tag

  • Create a new docker-compose file by copying above file content.

cd tag
sudo vim docker-compse.yml

  • Setup the entire JMeter-ReDis infrastructure with the below command.

sudo docker-compose up -d

  • Run the below command to see the running services

sudo docker-compose ps

   Name                  Command               State           Ports
-----------------------------------------------------------------------------
master        /bin/bash                        Up      60000/tcp
redis         docker-entrypoint.sh redis ...   Up      0.0.0.0:6379->6379/tcp
tag_slave_1   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp
  • Lets add more slaves by issuing below command.

sudo docker-compose scale slave=4


   Name                  Command               State           Ports
-----------------------------------------------------------------------------
master        /bin/bash                        Up      60000/tcp
redis         docker-entrypoint.sh redis ...   Up      0.0.0.0:6379->6379/tcp
tag_slave_1   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp
tag_slave_2   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp
tag_slave_3   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp
tag_slave_4   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp

  • Lets run one more command to get the all the IP addresses of the slaves.

sudo docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(sudo docker ps -aq)

/tag_slave_2 - 172.19.0.7
/tag_slave_3 - 172.19.0.6
/tag_slave_4 - 172.19.0.5
/master - 172.19.0.4
/redis - 172.19.0.3
/tag_slave_1 - 172.19.0.2

Pushing Data to ReDis:

Now lets move some data to the ReDis DB. Download the Jedis jar and and place it in the classpath – create some data. Or Read your CSV file and move the data to ReDis as shown here.

import redis.clients.jedis.Jedis;

Jedis jedis = new Jedis("server");
for(int i=1;i<=100000;i++){
	jedis.lpush("testdata", "name" + i + ",age" + i + ",address" + i);
}
jedis.close();	

 

JMeter Test Plan:

Lets create a simple JMeter test plan by using Redis Data Set. Redis key for the data is ‘testdata’ [Check the above java example for the key we had used]. If we comma separate each row, We have the data for name, age and address. Update the variable names accordingly. [If you are moving from CSV to ReDis, use the same variable names. That is it]

jm-redis-04

I have uploaded this test into Amazon S3 for us to access for testing purpose in the docker-containers.

JMeter-Distributed Test:

  • We have everything ready. Lets go inside the container as running below command.

sudo docker exec -it master /bin/bash

  • Go to JMeter bin folder.

cd jmeter/apache-jmeter-2.13/bin/

  • Download the JMeter-ReDis test plan i have created.

wget https://s3-us-west-2.amazonaws.com/dpd-q/jmeter/redis.jmx

  • Run the JMeter test

./jmeter -n -t redis.jmx -R172.19.0.2,172.19.0.5,172.19.0.6,172.19.0.7
jm-redis-05

 

Summary:

ReDis is a great option for sharing the data among all the slaves in JMeter distributed testing.  It does not affect your existing test plan. You just need to use ReDis Data Set config element instead of CSV Data Set.  It saves a lot of time from carefully splitting the file and distributing to all the slaves.

 

Happy Testing & Subscribe  🙂

 

 

Share This:

6 thoughts on “JMeter – How To Share Data In Distributed Load Testing

  1. Great post. I happened to face the same issue not long ago and implemented a similar solution, but using MongoDB instead of Redis just because we’re already using MongoDB in our application. It follows a similar concept, I used Mongoimport utility to import the csv, setup a MongoDB Source Config in the jMeter test plan and use JSR223 Sampler to read from MongoDB.
    I don’t know how it perform compares to Redis but I spawn 18000 threads in 5 minutes and so far there’s no issue reading from Mongo.

    1. Thanks Vincent for sharing. I had already taken a look at it. It did not look like a simple solution at all to me. I also do not want to make a lot of changes in the test plan. We can simply replace CSV Dataset config with Redis. It is much faster approach. Adding data at run time without affecting the test etc.

  2. How is it distributing the data among the slaves?
    Where is the setting that 2500 users are equally calling by each slave from redis?
    Can you please explain?

    1. The equal distribution is not in terms of number. Instead let the load machines ask for redis as and when they need. So that way redis keeps the load distributed among all the machines.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.