Jmeter and BeanShell

If you're using Jmeter for you load testing, and you not yet discovered BeanShell Server I can honestly tell that you are missing a lot. Seriously!

A little background

I'm a performance engineer at BSkyB, and couple of times a year we test how our platform reacts to all sorts of heavy load. We have been using Jmeter as our main tool, and from day one the biggest challenge was to have full control during load testing. As many of you know, Jmeter comes with build in Thread Group component. It works absolutely fine, but it's not very useful in real life. There is also Ultimate Thread Group plugin, which is great, but it was still not enough.

Imagine a 4 hours long load test, during that time you would probably like to control how many users try to login to your system, brows your website, recover login details etc. In many cases your company is running more then just one site, which makes it even more fun. On top of that you have your DevOps and PlatformOps engineers screaming from time to time that DB Servers|Web Servers|Cache Servers|Backend BlackBox is about to explode and you have to adjust the load immediately. It is almost like you need a big mixing console with uncountable number of knobs for adjusting all aspects of load test you are running. ... but all you really need is a BeanShell Server ;)

Our solution

We use a bunch of little test plans to build our main plan. Each script can be easily configured using user.properties file. Check out "Jmeter Test Plan Fragmentation" which explains how I split my test plans. Now imagine you can change these values with a little help from BeanShell while Jmeter executes your test plan, allowing you to shape load how ever you like :) - how awesome is that?

First you have to enable BeanSehll on your remote jmeter servers. To do that, put (uncomment) these lines in your bin/jmeter.properties

beanshell.server.port=9000
beanshell.server.file=./extras/startup.bsh

Default startup.bsh defines some basic functions like getprop, setprop, printprop and more. You can modify it or simply use another file with your common global functions/setup.

NOTE: Remember to include following line in your bootstrap file

// Stop exit() from calling System.exit();
bsh.system.shutdownOnExit = false;

Now all you need is a small script which you can use to control your test plan user properties. I'm using very simple script properties-control.bsh. And this is how you can use it to change login.sleep property to 500 over 5 minutes on jmeter01.company.net jmeter server.

$ alias jmeter01="java -jar ../lib/bshclient.jar jmeter01.company.net 9000"
$ jmeter01 bsh/parameter-control.bsh @update login.sleep 500 5m
 > UPDATE login.sleep (300s)
2000                                                                500
###############################

You can view my script in this gits.

Tips and Tricks

Stopping Remote Script Killing java process DOES NOT stop bsh script on remote server. This is very important if your script runs for few minutes.

Maximum Number of Threads One thing that you can't do with bsh is to spin-up new jmeter threads. That's why you need to estimate maximum number of threads, that will generate target load. For that run you test with disabled timers and get approximate execution time for one journey. Now simply calculate number of journeys and request for given number of threads.

Global Cache Globally defined functions are cached after first execution. When developing small, global functions you will have to restart jmeter to clear beanshell cache. In your custom scripts, simply use objects.

Comments