JMeter WebSockets发布/订阅-作为同步响应编写脚本

JMeter WebSockets发布/订阅-作为同步响应编写脚本,websocket,jmeter,stomp,Websocket,Jmeter,Stomp,我们通过WebSocket将发布/订阅模型构建到我们的应用程序中,这样用户可以在数据更改时接收动态更新。我现在希望使用JMeter对此进行负载测试 是否有一种方法可以配置JMeter测试,以对收到WebSocket发布的消息作出反应,然后运行进一步的采样器,即发出进一步的web请求 我看过插件示例,但它们似乎专注于请求/回复模型,例如,而不是发布/订阅 编辑: 我使用WebSocketSampler开发了一个解决方案——可以找到一个示例JMX文件,该文件使用STOMP over WebSocke

我们通过WebSocket将发布/订阅模型构建到我们的应用程序中,这样用户可以在数据更改时接收动态更新。我现在希望使用JMeter对此进行负载测试

是否有一种方法可以配置JMeter测试,以对收到WebSocket发布的消息作出反应,然后运行进一步的采样器,即发出进一步的web请求

我看过插件示例,但它们似乎专注于请求/回复模型,例如,而不是发布/订阅

编辑:


我使用WebSocketSampler开发了一个解决方案——可以找到一个示例JMX文件,该文件使用STOMP over WebSockets,包括连接、订阅、处理发布消息以及从中启动JMeter采样器

基本上,JMeter不适合与被测系统进行异步类型的交互

尽管使用脚本组件后处理器、计时器、断言(可能还有采样器)几乎可以实现所有功能,但在您的案例和JMeter逻辑控制器中,它们似乎最有用

类似地,您可以排列If块中包含的其他采样器,分析WebSocket发布消息的接收情况,并为If块设置标志变量/其他参数

您甚至可以同步线程,如果需要,请检查

但是告诉你吧,这看起来像是有很多手写的东西要做


因此,考虑全定制手写测试线束也是有意义的。

< P>我的系统有跺脚。因此,客户端执行HTTP消息,并通过使用此订阅模型的异步WebSocket获得实际状态。为了模拟这种行为,我编写了一个类,它可以通过JMeterContext变量与Jmeter threads import部件交换数据,您可以自己找到import org.springframework.*:

public class StompWebSocketLoadTestClient {

public static JMeterContext ctx;
public static StompSession session;

public static void start(JMeterContext ctx, String wsURL, String SESSION) throws InterruptedException {
    WebSocketClient transport = new StandardWebSocketClient();

    WebSocketStompClient stompClient = new WebSocketStompClient(transport);
    ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    threadPoolTaskScheduler.initialize();
    stompClient.setTaskScheduler(threadPoolTaskScheduler);
    stompClient.setDefaultHeartbeat(new long[]{10000, 10000});
    stompClient.setMessageConverter(new ByteArrayMessageConverter());
    StompSessionHandler handler = new MySessionHandler(ctx);
    WebSocketHttpHeaders handshakeHeaders = new WebSocketHttpHeaders();
    handshakeHeaders.add("Cookie", "SESSION=" + SESSION);
    stompClient.connect(wsURL, handshakeHeaders, handler);
    sleep(1000);
}
已在此类中处理消息:

private static class MySessionHandler extends StompSessionHandlerAdapter implements TestStateListener {

    private String Login = "";
    private final JMeterContext ctx_;

    private MySessionHandler(JMeterContext ctx) {
        this.ctx_ = ctx;
    }

    @Override
    public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
        session.setAutoReceipt(true);
        this.Login = ctx_.getVariables().get("LOGIN");
        //System.out.println("CONNECTED:" + connectedHeaders.getSession() + ":" + session.getSessionId() + ":" + Login);
        //System.out.println(session.isConnected());
        **//HERE SUBSCRIBTION:**
        session.subscribe("/user/notification", new StompFrameHandler() {

            @Override
            public Type getPayloadType(StompHeaders headers) {
                //System.out.println("getPayloadType:");
                Iterator it = headers.keySet().iterator();
                while (it.hasNext()) {
                    String header = it.next().toString();

                    //System.out.println(header + ":" + headers.get(header));
                }
                //System.out.println("=================");
                return byte[].class;
            }

            @Override
            public void handleFrame(StompHeaders headers, Object payload) {
                //System.out.println("recievedMessage");
                NotificationList nlist = null;
                try {
                    nlist = NotificationList.parseFrom((byte[]) payload);

                    JMeterVariables vars = ctx_.getVariables();
                    Iterator it = nlist.getNotificationList().iterator();
                    while (it.hasNext()) {
                        Notification n = (Notification) it.next();
                        String className = n.getType();
                        //System.out.println("CLASS NAME:" + className);

                        if (className.contains("response.Resource")) {
                            ///After getting some message you can work with jmeter variables:
                            vars.putObject("var1", var1);
                            vars.put("var2",String.valueOf(var2));
                        }
                        //Here is "sending" variables back to Jmeter thread context so you can use the data during the test 
                        ctx_.setVariables(vars);
                        n = null;

                    }
                } catch (InvalidProtocolBufferException ex) {
                    Logger.getLogger(StompWebSocketLoadTestClient.class.getName()).log(Level.SEVERE, null, ex);
                } 
            }

        });
    }
在Jmeter测试计划中,在登录阶段之后,我刚刚添加了一个带有登录/密码、会话字符串和Jmeter线程上下文的Beanshell采样器:

此外,还可以将所有通过Websockets传入的数据与简单vars变量一起使用:

Object var1= (Object) vars.getObject("var1");

这是一个误解,插件只支持请求-响应模型对话

自版本0.7以来,该插件提供单读和单写采样器。当然,这取决于您的具体协议,但是您可以使用一个写采样器来发送一个WebSocket消息,该消息模拟创建订阅,然后使用一个标准JMeter While循环与单读采样器结合,来读取任何数量的正在发布的消息


如果这不能满足您的需要,请告诉我,我会看看我能为您做些什么。我是这个插件的作者。

试试ZebraTester。它支持websockets@Vinit谢谢-我会检查一下-如果您知道ZebraTest支持异步回调风格的用法,那么JMeter通过插件支持WebSocket,这会有所帮助。因为我们已经在JMeter上投入了时间等,所以我很想看看我是否可以先让它工作起来,这将在即将发布的Zebratesters版本中提供。我们实际上在WebSocketsah上使用了STOMP,但目前不受支持,或者在路线图上。谢谢——我也这么认为,但没有深入了解细节——我只是希望我错过了一些东西。我将看一看你链接的线程间选项。这看起来非常有趣-我们也在使用STOMP,因此可能是一个很好的选择。我看到了通过处理程序的回调——在这里,我看到了设置JMeter变量,我正在努力解决的问题是如何触发进一步的活动——即如何在测试中注入进一步的样本——对于我们来说,这主要是通过HTTP从API刷新数据。这是否需要一个LoopControl,比如在第一轮时连接并发送初始页面请求,并且如果数据变量集(即消息接收)发出刷新,则需要一个LoopControl?没有完全理解您的问题,但是在你与这个例子建立了联系之后,任何数据都可以通过VAR在任何jmeter采样器中使用,这些数据都可以通过这个SUNSCRIED通道获得。好的,谢谢,我得到了要点-我的问题是关于处理多个发布响应的jmeter控制结构,但我想我能解决它。我错过了这一点-我会仔细看看。根据问题编辑-我已经在使用WebSocketSamplers方面取得了进展,包括在消息接收时启动JMeter采样器,所以接受这一点作为我问题的答案。
Object var1= (Object) vars.getObject("var1");