Jmeter websocket testing: how to use existing connection between thread groups - websocket

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

Related

How do we run multi concurrent sessions Websocket testing using JMeter?

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.

Finish and start with other Threadgroup

I'm using Jmeter to test multiple microservice.
The basic idea is to test a circuit breaker in a microservice environment.
Right now, I'm using two threadgroups, a master and slave remote concept.
One thread group creates uses 100 iterations and 1000 thread and creates
load against a front-end service, which sends request to a backend service.
The other group probes the backend service with 100 iterations but 1 thread.
If I’m not wrong the second threadgroup finishes way more early than the first one.
Is it somehow possible to sync those two?
And maybe another question.
As I scale the threads with the remotes, also the second thread group scales, is it possible to force the second threadgroup to use only one slave?
In order to execute "probe" thread group until "main" thread group is executing put the "probe" request under the While Controller and use the following __groovy() function as the condition:
${__groovy(org.apache.jmeter.threads.JMeterContextService.getThreadCounts().activeThreads > 1,)}
If you want to execute the "probe" thread group only on one machine of the JMeter cluster - put the whole construction under the If Controller and use the following jexl3() function as the condition:
${__jexl3("${__machineIP()}" == "IP address of the slave",)}
The whole Thread Group should look like:

How to have requests in a thread group where a set of requests has a same data field (which is different from other sets)?

I have two separate thread groups in jmeter,
First Thread Group: All the Users corresponding to first thread group are responsible to hit an API which creates a user and return userId in response
Second Thread Group: All the Users corresponding to second thread group are responsible to hit an API which uploads photo for created users and uses userId (returned in previous response) as its request data.
I have used InterThreadCommunication plugin of jmeter and so userID from response of API hit of first thread group get mapped to request data of API hits of second thread group.
The problem is that in Thread Group 2, I need to run upload image of user 5 times (in order to have a set of images corresponding to each user). How can I extend InterThreadCommunication functionality to map one userId from threadGroup1 to 5 requests of threadGroup2 (and similarly another userId to another 5 requests)
Current Implementation:
Thread Group 1:
jp#gc - Inter-Thread Communication PostProcessor:
FIFO Queue Name to put Data in: userIdList
valueToPut: $userId
Thread Group 2:
jp#gc - Inter-Thread Communication PreProcessor
FIFO Queue Name to get Data from : userIdList
variable name to store Data: userId
Thread Group 2 request data , I am using value as $userId
Just get it once using Once Only Controller and execute the request 5 times using Loop Controller
If Inter-Thread Communication Plugin is not flexible enough to fit your needs you can always switch to another approach of passing the values between Thread Groups, i.e.
Use __setProperty() and __threadNum() functions combination to store the value in 1st Thread Group like:
${__setProperty(userid_${__threadNum}, YOUR_VALUE_HERE,)}
Use __P() and __threadNum() functions combination to read the value in 2nd Thread Group like:
${__P(userid_${__threadNum},)}
Check out Apache JMeter Functions - An Introduction article for more information on JMeter Functions concept.

How to execute HTTP sampler by only one thread at a time in JMeter

My application is not allowing to execute one of the HTTP sampler by multiple threads at a time and throwing "RECORD_LOCKED" exception. So please suggest how to create synchronized sampler(should be execute only one thread at a time ) to solve this issue.
Assume below are my samplers in Thread group and I want to run this thread group with 10 threads. But the 2nd HTTP sampler should be executed by only one thread group at a time. After login completion(2nd sampler) of one thread then only another thread should execute that sampler.
Thread Group 1
Login page HTTP Sampler
Enter UserName / Password and click on Login HTTP Sampler
Home Page View HTTP Sampler
To Lock the specific Sampler from other threads use the controller:
Right click the HTTP Sampler-> Insert Parent -> Logic Controller -> Critical Section Controller
Critical Section Controller ensures that its children elements (samplers/controllers, etc.) will be executed by only one thread

JMeter: Stop Thread Group after first HTTP request fails

I am testing a mobile app, and I have a Thread Group with about 40 HTTP requests, with the first being an access token request. What I want to do is if the access token fails, skip that current thread iteration.
There are at least 3 options:
You can define what action to take on sampler error on Thread Group level
If you need to limit this behavior to one sample add a Result Status Action Handler as a child of the request
If you need to skip current iteration based on certain condition use Test Action sampler in combination with If Controller

Resources