2017-02-23 176 views
1

我们已经通过WebSockets为我们的应用程序构建了发布/订阅模型,因此用户可以在数据更改时接收“动态更新”。我现在正在使用JMeter来加载测试。JMeter WebSockets发布/订阅 - 脚本异步响应

有没有一种方法来配置JMeter测试,以应对收到的WebSocket的“发布”的消息,然后运行进一步采样即做出进一步的Web请求?

我已经看过插件样本,但他们似乎集中在请求/响应模式(例如https://bitbucket.org/pjtr/jmeter-websocket-samplers),而不是发布/订阅。

编辑:

我已经进展使用WebSocketSampler了一个解决方案 - 为例JMX文件可以发现on BitBucket其使用STOMP过的WebSockets并包括连接,从订阅,手柄发布消息和启动JMeter的取样那。

+0

尝试使用ZebraTester。它支持websocket – Vinit

+1

@Vinit谢谢 - 我会检查出来 - 如果你知道ZebraTest支持异步(回调)风格的用法,JMeter支持WebSockets(通过插件),这将有所帮助。由于我们已经在JMeter投入了时间,所以我很想看看我能否先做好这项工作。 – Dazed

+0

如果您正在通过网络套接字讨论MQTT,那么即将推出的ZebraTester版本将提供 – Vinit

回答

1

它是一种误解的是,https://bitbucket.org/pjtr/jmeter-websocket-samplers/overview插件只支持请求 - 响应模型的会话。

从版本0.7开始,插件提供“单次读取”和“单次写入”采样器。当然,这取决于你的确切协议,但想法是你可以使用“单写”采样器发送模拟创建订阅的WebSocket消息,然后将(标准JMeter)While循环与“single阅读“采样器,阅读任何数量的正在发布的消息。

如果这不能满足您的需求,让我知道,我会看看我能为你做什么(我是这个插件的作者)。

+0

我错过了 - 我会仔细看看。 – Dazed

+0

按照编辑的问题 - 我已经使用WebSocketSamplers进行了改进,包括在消息接收时启动JMeter采样器,因此接受这个作为我的问题的答案。 – Dazed

0

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

虽然(几乎)一切皆有可能用脚本组件(后置处理器,定时器,断言,也许采样,似乎看你的情况最有用)和JMeter的逻辑控制器。

一样,你可以排队你的“进一步采样器”,覆盖如果块,分析了“收到的WebSocket已发行消息”,并设置标志变量/其他参数如果块。

你甚至可以同步线程,如果你需要它,检查this answer

但告诉你什么 - 这看起来像很多手写的东西要做。

因此,考虑整个自定义手写测试工具也是有意义的。

+0

谢谢 - 我正在考虑同样的线条(没有深入细节) - 只是希望我错过了一些东西。我会看看你链接的“线程间”选项。看起来非常有趣的 – Dazed

0

我用STOMP系统。所以客户端执行HTTP消息,并通过这个订阅模型的异步WebSocket获得实际状态。为了模拟这种行为我写了通过JMeterContext变量可以用JMeter线程交换数据的类(进口部分你可以自己找到进口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中测试计划,登录阶段之后我只是增加了一个BeanShell的取样与登录/密码和会话串和的JMeter线程上下文

import jmeterstopm.StompWebSocketLoadTestClient; 
StompWebSocketLoadTestClient ssltc = new StompWebSocketLoadTestClient(); 
String SERVER_NAME = vars.get("SERVER_NAME"); 
String SESSION = vars.get("SESSION"); 
String ws_pref = vars.get("ws_pref"); 
ssltc.start(ctx,ws_pref+"://"+SERVER_NAME+"/endpoint/notification- ws/websocket",SESSION); 

此外,可以使用通过WebSockets的数据的所有传入与简单瓦尔变量:

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

- 我们也使用STOMP,因此非常适合。我通过“处理程序”看到了回调 - 在那里,当我看到设置JMeter变量时,我正在努力的是如何触发进一步的活动 - 即如何在测试中注入更多样本 - 对我们来说,这主要是refreshData从API通过HTTP。这需要一个LoopControl(比如说)在第一次连接并发送初始页面请求,并且如果数据变量集(即接收到的消息)发出刷新? – Dazed

+0

没有完全得到你的问题,但是在你建立与这个例子的连接之后,任何将来到这个明文通道的数据将可以通过变量在任何jmeter采样器中使用。 – v0devil

+0

好的,谢谢我得到的要点 - 我的问题是关于JMeter控制结构来处理多个发布响应,但认为我可以解决它。 – Dazed