WebSocket is a protocol which provides full-duplex bi-directional communication over a single TCP connection using default HTTP and HTTPS ports. It is supported by the majority of modern web browsers and is used to create chats, real-time games and applications, etc. The main idea of the protocol is that one connection is being used for two-way communication, as opposed to Ajax/iframes/XMLHttpRequests.
WebSocket is a fully independent from the HTTP TCP-based protocol, as described in RFC 6455.
At the moment the only easy way to implement WebSocket testing with JMeter is to use JMeter WebSocket Sampler by Maciej Zaleski. It's the only RFC6455-compliant extension which supports reusing one TCP session and it is easy to install and use.
To install JMeter WebSocket Sampler go to the JMeter Plugins Manager. This is also the best way to keep the Sampler up to date.
If you need to install manually, do the following:
Notes:
This section explains the WebSocket Sampler GUI elements.
For version 1.0.1 the following components are available for the WebSocket Sampler:
Other fields are self-explanatory.
For this demonstration we'll be using Echo Test WebSocket Demo which uses the ws://echo.websocket.org endpoint which basically responds to client with the same message it received.
Let’s assume the following Test Plan structure:
We're going to send 2 messages one by one through one session via Loop Controller followed by 1 message via another session.
Here’s the Blazemeter aggregate report:
And the Blazemeter Engine log:
The results show that the message “Ground control to Major Tom” went through the same WebSocket Session (red rectangles) and the message “Take your protein pills and put your helmet on” went through another session which was closed right after response.
The first session disconnected on the test run end (or if “Close Connection Patten” is provided and matches).
That’s how the WebSocket Sampler from Maciej Zaleski can be used for JMeter WebSocket testing, supported by Blazemeter as an extension. Any enhancements? send pull request to GitHub.
Any questions? – feel free to shout.
Need a missing feature right away? Your WebSocket server-side tier uses a specific protocol or authentication? Want your own implementation or to override connect, message and disconnect event? We won’t give you a fish. We’ll teach you how to fish.
The JMeter WebSocket extension discussed above uses Jetty client libraries. Another implementation of WebSocket is JSR 356 (Java API for WebSocket). We'll tell you about how to create a WebSocket extension based on a JMeter Java Request Sampler.
Java Request Samplers are classes which implement the JavaSamplerClient interface. All classes which have appropriate JavaSamplerClient methods implementation and existing in JMeter classpath will be automatically picked up and displayed within the JMeter – Sampler – Java Request drop down.
In this example, once again, we will use the echo.websocket.org endpoint which will send a “Blazemeter rocks” message and wait for the answer.
First of all we'll need Tyrus – an open source JSR-356 implementation. Tyrus requires Java 7 so make sure that you use Java SE 7 to build and execute the extension.
The most convenient way of getting dependencies is using the following Apache Maven configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>blazemeter-websocket</groupId>
<artifactId>blazemeter-websocket</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-client-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</project>
Invoking the target “mvn dependency:copy-dependencies” will download all required jars into /target/dependency folder. However you may wish to continue with build, package, etc. maven plugins.
The source code of the extension is follows:
package com.blazemeter;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import org.glassfish.tyrus.client.ClientManager;
import javax.websocket.*;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ClientEndpoint
public class BlazemeterWebsocketRequest extends AbstractJavaSamplerClient {
private static String ws_uri;
private static String ws_message;
private static String response_message;
private static CountDownLatch latch;
private static final Logger log = LoggingManager.getLoggerForClass();
@Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument("URI", "ws://echo.websocket.org");
params.addArgument("Message", "Blazemeter rocks!");
return params;
}
@Override
public void setupTest(JavaSamplerContext context) {
ws_uri = context.getParameter("URI");
ws_message = context.getParameter("Message");
}
@Override
public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
SampleResult rv = new SampleResult();
rv.sampleStart();
latch = new CountDownLatch(1);
ClientManager client = ClientManager.createClient();
try {
client.connectToServer(BlazemeterWebsocketRequest.class, new URI(ws_uri));
latch.await(1L, TimeUnit.SECONDS);
} catch (Throwable e) {
throw new RuntimeException(e);
}
rv.setSuccessful(true);
rv.setResponseMessage(response_message);
rv.setResponseCode("200");
if (response_message != null) {
rv.setResponseData(response_message.getBytes());
}
rv.sampleEnd();
return rv;
}
@OnOpen
public void onOpen(Session session) {
log.info("Connected ... " + session.getId());
try {
session.getBasicRemote().sendText(ws_message);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@OnMessage
public String onMessage(String message, Session session) {
log.info("Received ... " + message + " on session " + session.getId());
response_message = message;
try {
session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE,""));
} catch (IOException e) {
e.printStackTrace();
}
return response_message;
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
log.info(String.format("Session %s close because of %s", session.getId(), closeReason));
}
}
The Sampler GUI may look minimalistic…
… but it is a fully functional WebSocket client
This is pretty enough for a proof-of-concept assessment, and you also have full code control and can, for example, change the protocol by playing with annotations like @ClientEndpoint(subprotocols= { “xsCrossfile”})
The same stands for custom headers, cookies, or whatever logic you need on connection open, close and message events.
Happy WebSocket testing! Don't hesitate to post your questions and comments.
P.S. :
You may find references to the https://github.com/kawasima/jmeter-websocket/ plugin across the Web and some evidence of successful WebSocket testing with the plugin.
We aren’t saying it is a bad plugin but we do recommend using it with caution as it wasn't updated for 2 years and it relies on the 8.1.9.v20130131 Jetty libraries version which not fully RFC6455 compliant, but rather a kind of experimental draft. It also doesn't seem to support reusing one TCP session (this is how browsers work and the majority of test cases will be connected with sending lots of messages through one session).
Learn more about JMeter from our free webinars:
"How to Make Performance Testing with JMeter Simple"
联系客服