I was using the JMeter WebSocket Samplers to perform WebSocket latency testing. My test plan contains 4 thread groups.
Firstly, here is the order of operations I was producing, each step is grouped in a thread group. And the connection for the 1st. operation on Presenter was cached before executing the 2nd. operation because the 3rd. operation, the same Presenter, is gonna continue to use this connection.
def connection = sampler.threadLocalCachedConnection
props.put('presenterConnection', connection.get())
Same idea for the 2nd & 4th connection for Participant. The participant at step 4 is gonna continue to use the connection created at step 2.
Presenter connects to WS, creates session & saves the session id
Participant connects to WS & subscribes to the saved session
Presenter sends out commands
Participant reads the commands that were sent by Presenter
It worked as expected with single session. However I ran into an issue with the WebSocket Single Read Sampler at the 4th operation of reading commands that were sent from Presenter when I was running 2 concurrent sessions.
I changed the "Number of Threads" to 2 in the thread properties of each thread group. The presenter was able to create 2 session IDs at the 1st. operation. And I added the "Inter-Thread Communication PostProcessor" to store the session IDs in a queue such that it's able to be passed to other thread group. It worked for the first 3 operations until it went to the WebSocket Single Read Sampler in the last operation of reading the commands that were sent from the Presenter.
I had a JSR223 PreProcessor in place to use the cached connection at step 2.
def connection = props.get('Participant1Connection')
sampler.threadLocalCachedConnection.set(connection)
The issue was found in the response body of the 2 threads of the last operation. The first session ID was not being used. The first user at step 4 was using the 2nd session ID and the 2nd response body was empty because the 2 users were using the same session. What shall I do to fix this issue to have 2 users reading data from 2 sessions created accordingly?
This is something which normally happens when people copypaste the code without understanding what it is doing. Moreover if you need to pass data between thread groups most probably there is a problem with your test design.
Whatever.
As per JMeter Documentation:
Properties are not the same as variables. Variables are local to a thread; properties are common to all threads
So when you have > 1 thread (virtual user) the second thread overwrites the value of the presenterConnection property so no matter how many threads you have they all are trying to use single instance of the presenterConnection
My expectation is that you want a connection per thread, in this case you should add current thread number as a prefix/postfix for the property key so:
1st thread would use presenterConnection1
2nd thread would use presenterConnection2
etc.
Amendment to "your" code would be something like:
props.put('presenterConnection' + ctx.getThreadNum(), connection.get())
similarly for accessing the connection.
In the above example ctx stands for JMeterContext class instance, see Top 8 JMeter Java Classes You Should Be Using with Groovy article for more information on this and other JMeter API shorthands available for the JSR223 Test Elements.
Related
Firstly I was using the JMeter WebSocket Samplers. here is the order of operations that I needed to accomplish:
Presenter connect
Presenter create session; save session id
Participant connect
Participant subscribe to commands for saved session id
Start latency test
So based on the flow, I'm gonna need 2 connections to different endpoints (one is for presenter and the other is for participant).
I needed to make sure the first 4 steps are completed and both presenter and participant connect to the web socket successfully before I start the latency test.
I created 2 thread groups and connected to the endpoints for presenter and participant accordingly. My question is how do I manage to have the requests in the 2 thread groups executed in a specific order? Follow the order, I'd like to execute
Login->Connect->Subscribe in the Presenter thread group
Connect->Subscribe in the participant thread group
send request in the Presenter thread group
The loop controller(which contains a WebSocket Single Read Sampler) in the Participant thread group.
I tested it by putting the send request in a 3rd thread group, and then check run thread groups consecutively option in test plan. But the WebSocket single write sampler in the send request was not be able to use the existing connection anymore. (And there were 2 connections out there for presenter and participant)
And I am a little confused about the order of execution with my current setting. Looks like there were being executed randomly. The first 4 requests within participant thread group looks like being executed before any requests in the presenter thread group in the snapshot below, which messed up the data because the highlighted subscribe request in participant thread group was dependent on the session id that will be passed from request (WS-Subscribe-Presenter-/v1/create/session)in the presenter thread group. Due to the wrong order of execution, the session id that was passed to here was actually not the same session id that was created from the presenter request in this round of test run. It was actually still using the session Id that was created in the previous round of test run.
Note: I passed the session ID as a property such that the value can be passed between thread groups.
import groovy.json.JsonSlurper;
def response = prev.getResponseDataAsString();
String[] res = response.split();
def json = new JsonSlurper().parseText(res[res.size() -1]);
vars.put("sessionUUID", json.data.sessionUUID);
props.put("sessionId", vars.get("sessionUUID"));
Add a JSR223 PostProcessor as a child of the last WebSocket Sampler in 1st Thread Group
Put the following code into "Script" area
def connection = sampler.threadLocalCachedConnection
props.put('connection', connection.get())
Add a JSR223 PreProcessor as a child of the first WebSocket Sampler in 2nd Thread Group
Put the following code into "Script" area:
def connection = props.get('connection')
sampler.threadLocalCachedConnection.set(connection)
More information on what do these sampler and props mean: Top 8 JMeter Java Classes You Should Be Using with Groovy
I am using "WebSocket Samplers by Peter Doornbosch" plugin
The system will send a heartbeat message to the client every 30 seconds.
The client must respond for not disconnect to the system.
I want to do the heartbeat part without pausing the current testing process.
What I tried:
Create a Single read sampler in While timer. It will pause the testing process.
Create two thread groups. The Websocket object (connection ID) cannot be shared between two thread groups.
Tried plugin -- Parallel Controller & Sampler, unfortunately it cannot share the websocket object as well.
Edit:
For 2, I want the websocket object can be shared between threads.
1 thread for heartbeat job, 1 thread for doing test. Even I input the same connection ID in the second thread, jmeter still treat it as different object.
You cannot share a websocket connection between threads. This is by design. The solution for your use case is having a single read sampler with a timeout of 30 seconds, followed by a sampler that responds to the heartbeat. You can use the "optional read" option with the read sampler to avoid it generates an error when no message is read during this 30 second period.
The Websocket object (connection ID) cannot be shared between two thread groups.
actually it is possible, as per JMeter Documentation:
Properties are not the same as variables. Variables are local to a thread; properties are common to all threads
so there are 2 options for sharing the data between different threads (even if they're in different thread groups)
Use __setProperty() function to convert JMeter Variable into a JMeter Property in first Thread Group and __P() function to read the value in 2nd Thread Group
If your use case is more complex and you want i.e. to wait until connection ID is available you can consider using Inter-Thread Communication Plugin
In my Jmeter script request which contains the 'LongPolling' transport method and it takes a high load time or response time
Also, the response message content value is used for the next consecutive request. How can I handle that scenario?
I don't want this my wait time for the server response
JMeter thread model assumes that a thread (virtual user) always waits for the previous sampler to fully complete before starting the new one.
The easiest solution is moving your "long-polling" requests into a separate thread group and if you need to pass data between thread groups either use __setProperty() and __P() functions combination or go for Inter-Thread Communication Plugin
If you need to have everything within the single Thread Group - you can consider using Parallel Controller, however it might not be fully suitable for your needs as it is still a Sampler hence it waits for all its children completion prior to proceeding
Depending on your use case you can find jmeter-asynchronous-http plugin useful, see How to Load Test Async Requests with JMeter article for more details if needed.
I'm trying to load test our web app server side with JMeter, everything works so far except one thing.
I have a heartbeat loop the app client side that pings the server every x seconds.
I tried the while processor but then the thread is just "stuck" there (as expected).
Is there a way to execute a request every x seconds while the other requests are still executing?
I also would need access to the variables of my thread since the heartbeat sends a unique id, so another thread group won't work as far as i understand.
The id is read from one of the first request responses into a variable so the heartbeat requests should only start when this variable becomes available.
Another separate Thread Group to send heartbeat requests is the easiest way to achieve, if you need to pass a value from the "main" thread group you can do it in 2 ways:
Use __setProperty() function in the "main" thread group to convert the variable into a property and use __P() function in 2nd Thread Group to read the value. If you have more than 1 thread it makes sense to add __threadNum() function to make the value thread-specific.
Use Inter-Thread Communication Plugin if you don't mind using JMeter Plugins
Good day, guys!
What I attempting to do is perform a clean logout for all users after test stops running via duration restriction.
In my case, when user logs in, he gets unique session id parameter that makes it impossible to log with same user from different tab/browser/place, so I need to be sure that user is not blocked after my test completes.
Lets say I use 100 users for a test.
My test looks something like:
Login (get session id)
do stuff
do stuff
Logout (terminate session)
It works fine when I use a constant set of loops, but when I run test with duration, for example, 600 seconds, test stops in the middle after time runs out and my users are blocked until their sessions expire by timeout.
I tried to create a second thread which also contains 100 users and only a logout HTTP sampler, passed and used session id variable to it as described in article https://www.blazemeter.com/blog/knit-one-pearl-two-how-use-variables-different-thread-groups but it seems that my second thread receives only a last session id value so it basically logs out 1 user 100 times, but I need to log out 100 users 1 time.
Does anyone now how to store multiple values of a variable and use them in correct order in other threads?
Not a programmer, just a manual tester with some extra responsibilities.
Thank you.
JMeter Variables are local to each thread, JMeter Properties are global for the whole JVM so if you're passing variables between thread groups make sure you add current thread number as a prefix (or postfix) for the generated property, something like:
In the first Thread Group define user-specific property using __setProperty() and __threadNum() functions combination:
${__setProperty(foo_${__threadNum},${YOUR_VARIABLE_HERE})}
In the second Thread Group get user-specific property using __P() and __threadNum() functions combination:
${__P(foo_${__threadNum},)}
Replace foo with the property name of your choice
Replace YOUR_VARIABLE_HERE with the name of the relevant JMeter Variable
Demo:
See Apache JMeter Functions - An Introduction to get familiarized with JMeter Functions concept.