Using Websocket samplers in JMeter with STOMP

Issue #39 closed
Former user created an issue

Hi Peter,

We have websockets implemented as follows: A file is uploaded into the server via HTTP and then a Websocket connection is established between the client and the Websocket service which will send a Message (similar to the below) to the client once the file got processed (by some other service) using this Websocket connection. The client once receives the Message from websockets-api, it will update the flag to see the update on the UI.

SUBSCRIBE id:sub-0 destination:/test/fProcess.1234567890123456 PING <<< PONG PING <<< MESSAGE subscription:sub-0 destination:/test/fProcess.1234567890123456 message-id:T_sub-0@@session-11111session-id11111 redelivered:false content-type:application/json;charset=UTF-8 content-length:269

I am trying to load test to measure the file processing times by capturing the timestamps when client receives Messages sent by the Websocket service. Can you help with steps to test this using these Websockets samplers?

Thanks in advance. SS

Comments (23)

  1. Peter Doornbosch repo owner

    Upload a file with a standard JMeter HTTP sampler, open the websocket connection with a "WebSocket Open Connection" sampler and wait for the message with a "WebSocket Single Read" sampler. Seems pretty simple to me, maybe i'm missing your point....

  2. Shashidhar A

    I have added Open Connection and Single Write and Single Read Samplers as suggested. But I see the message "Close frame with status code 1007 and close reason 'null'" sent by the ws server in "JMeter - View Results Tree" Listener. Attached the screenshots of all the screens and also the screenshots of Chrome Dev Tools and Fiddler when I open ws connection thru Chrome browser. Can you please take a look at them and help me here?

  3. Peter Doornbosch repo owner

    Hi,

    1007

      1007 indicates that an endpoint is terminating the connection
      because it has received data within a message that was not
      consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
      data within a text message).
    

    So your server doesn't get it; probably your test plan is not exactly conforming to the protocol (i.e. the protocol on top of ws; the format / sequence of the messages) the server is expecting.

    I cannot help you with that, because i don't the protocol your server is talking. If this is not documented, you could use a protocol sniffer to see what your normal client application is sending to the server and then try to reverse-engineer what the protocol should look like.

    Unfortunately, this is an issue that more people run into; for example see https://bitbucket.org/pjtr/jmeter-websocket-samplers/issues/32/problem-with-writing-text-message-to-a (specifically: "Socket.io / Engine.io has its own protocol that it talks on top of the ws connection. Unfortunately, this is not very well documented, but with a little help from wireshark and stackoverflow.........").

    Hope this helps. Regards Peter

  4. Shashidhar A

    Hi Peter, We are using STOMP protocol on top of WS. The below is the javascript that Dev is using in a test page to functional testing of the same WS from the browser. They are also using "jquery.min.js", "sockjs.min.js" and "stomp.min.js". Please see if you get some pointers to help me.

    function connect() {
        var socket = new SockJS('/ds1-websocket');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function (frame) {
            setConnected(true);
            console.log('Connected: ' + frame);
            var parentId = $("#parentId").val();
            if (parentId==null)
                parentId = "*";
    
            stompClient.subscribe("/topic/docProcess." + parentId, function (event) {
                showProcessing(JSON.parse(event.body).id);
            });
        });
    }
    
  5. David Hubbard

    Hi

    I'm also using STOMP and hitting the same problem (I can start another thread, but thought I could add to this)

    My thinking is that the STOMP messages defined here ["Example" down the bottom of the page] and better still in STOMP Spec - have a "NULL (0x00)" character at the end of the Text-based frame/message.

    So the problem is trying to put in TEXT (which the main part of message is) with a Non-Text character at the end.

    I have attempted to inject this with a BeanShell PreProcessor and inject a JMeter variable.

    String s = "CONNECT\n" +       
           "login:#token-here#\n" +
                       "passcode:\n" +
                       "accept-version:1.1,1.0\n" +
                       "heart-beat:20000,0\n" +
                       "\n\0";
    vars.put("wsStompData", s);     
    

    And then trying to use ${wsStompData} on the "WebSocket Single Write Sampler" with no success - I get "Request data is not binary: ${wsStompData}" - the GUI screen implies this is supported - when I type in non binary data it says "JMeter variables like ${var} are allowed".

    Can you assist?

  6. Peter Doornbosch repo owner

    Hi David,

    Thanks for contributing to this thread. I agree the null character might be the problem.

    • Is STOMP over websockets using (ws) text frames or (ws) binary frames?
    • "request data is not binary": when using binary frames, the sampler expects you to provide data in hex format. So you can use a JMeter variable like ${var}, but the value of var should be in hex.

    Hth Peter

  7. David Hubbard

    Peter hi,

    I believe it's Text - as I can see the text content in Chromer Frames with a red dot for the Null.

    One problem was that I wasn't actually setting the variable correctly - the Beanshell was failing with the "\0" in the string.

    If I set the variable directly I can see WebSocketSampler sending in Text mode

    I'm focussing in on a way to get that NULL into the string - will update. I'm now looking for a

    The use of ${wsStompData} works in WebSocker Sampler" - it's just not getting set in PreProcessor - I believe it's tripping up add the "\0" to the String setup. Will update if I find a resolution to that.

  8. Peter Doornbosch repo owner

    Hi David,

    In the mean time, i found out that this works to get a null in a string with beanshell:

    String s = "with" + '\0' + "null";

  9. David Hubbard

    Peter hi

    Thanks, added a char, rather than as part of String, did the trick - got it working - Connecting, Subscribing and Reading from Stomp.

    String s = "CONNECT\n" +       
           "login:${wsToken}\n" +
                       "passcode:\n" +
                       "accept-version:1.1,1.0\n" +
                       "heart-beat:20000,0\n" +
                       "\n" + 
                       '\0'  // note: NULL char at end
                       ;
    
    vars.put("wsStompData", s);         
    

    For others - after Connect a Read Sampler is required to comsume the "CONNECTED" response message. One thing I haven't considered/covered at the moment is the heartbeat messages which may be required outbound and handled to keep a connection open.

    Happy to post a JMeter Example .jmx file if you tell me how to do that.

  10. David Hubbard

    Hi

    Just to add to this - as I had a few further problems getting the response data.

    STOMP Message returned

    MESSAGE
    expires:0
    correlation-id:
    destination:/topic/mytopic
    subscription:sub-0
    priority:0
    type:
    message-id:ID\cmyserver.company.com-56722-1504182470511-4\c7514\c1\c1\c31
    timestamp:1504362991419
    
    DATA BODY<NULL>
    

    So in a BeanShell PostProcessor methods like this gave exception due to the NULL char in the returned data,

    String dataString = new String(data);
    

    But I managed to extract via prev.getResponseDataAsString();

    String  dataString = prev.getResponseDataAsString();
    
    System.out.println("Response\ngetResponseDataAsString["+dataString+"]\n");
    
    String[] parts = dataString.split("\n");
    
    if (parts.length >= 11) {
          String rType = parts[0];
          String rBody = parts[10];
          System.out.println("Body ["+rBody+"]");
    }
    
  11. David Hubbard

    An update - heartbeating is another problem area, but I managed by turning heartbeating (from client) off (I'm using ActiveMQ 5.15.0)

    Without this my connection kept dropping

    String s = "CONNECT\n" +       
           "login:${wsToken}\n" +
                       "passcode:\n" +
                       "accept-version:1.1,1.0\n" +
                       "heart-beat:0,0\n" +
                       "\n" + 
                       '\0'  // note: NULL char at end
                       ;
    
    vars.put("wsStompData", s);         
    
  12. Shashidhar A

    Thanks David and Peter for the above details.

    David, I tried to follow the above solution, but I still could not receive the "CONNECTED" frame. Can you please share a sample JMX. The STOMP frames for my test are seen in attached screenshot (from Chrome DevTools - Console). Chrome-DevTools-Console.png

  13. David Hubbard

    Hi

    Try this bitbucket link - you'll need to change the User Parameters at the top of the Thread Group and also some of the content of the Connect Beanshell e..g. remove the login/password fields.

    I might also suggest that you check the MQ Server logs

    Plus check via Network > WS that you are injecting the NULL char correctly (red dot)

    Stomp_Connect.png

  14. Shashidhar A

    I was still facing this issue, but didn't get chance to follow up with David for help. I will circle back once I switch to the Websockets testing again.

    Thanks, Shashidhar

  15. utsav kansara

    Hi Guys,

    I am using spring boot with sockjs and stomp. Can someone please provide sample test plan if you were successful with your test. That would be really helpful.

    Thanks Utsav

  16. Александр Мужичек

    Hi @Peter Doornbosch !

    Could you please help me with my issue - I used this suggestion for Stomp

    String s = "CONNECT\n" +       
           "login:${wsToken}\n" +
                       "passcode:\n" +
                       "accept-version:1.1,1.0\n" +
                       "heart-beat:0,0\n" +
                       "\n" + 
                       '\0'  // note: NULL char at end
                       ;
    
    vars.put("wsStompData", s);
    but this approach is not working for SockJS.
    

    Could you please paste here the correct “connect” request fir SockJS?

    Thanks a lot.

  17. Peter Doornbosch repo owner

    Hi,

    No, i can’t and i won’t. I am not giving support on STOMP, i don’t know nothing about STOMP. You can use the plugin to test or simulate STOMP as other contributors to this issue have shown, but i cannot help you with that.

    Regards
    Peter

  18. Log in to comment