zoukankan      html  css  js  c++  java
  • jmeter测试基于SignalR的Websocket过程中的一些总结

    引言

    ASP.NET Core SignalR 作为微软官方出品的一个实时Web中间件功能库,可以使服务器端代码可以将内容立即推送到客户端。

    SignalR supports the following techniques for handling real-time communication (in order of graceful fallback):

    SignalR automatically chooses the best transport method that is within the capabilities of the server and client.

    背景

    ​ 在使用jmeter对自己搭建的聊天服务(消息转发服务)进行压力测试的时候,发现和传统的websocket连接测试过程不同,比如websocket连接地址是什么,端口是什么,这些都不是signalr去暴露出来的,因此进入了深一步的研究。

    ​ 通俗来讲,SignalR只是一个实时Web的中间件,它支持的通讯模式有WebSocketsSSELong Polling ,目前我们只考虑最优的websocket模式,那么它的websocket地址是什么呢?

    ​ 因为我是将SignalR中间件寄宿于Web MVC中,然后部署在Linux下,所以这里websocket的地址就是 127.0.0.1/chatHub ,后面的名称,具体的路由地址,看你再starup.cs中如何映射SignalR请求地址和后台中的Hub名称。

    过程分析

    通过web端监控,发现连接客户端连接SignalR会执行两个步骤

    negotiate

    返回的结果,注意看下这个connectionToken ,这个token会作为 一个参数在接下来的chatHub中去请求服务器。

    {
      "negotiateVersion": 1,
      "connectionId": "eZuczhINi9cewADWJO4kXA",
      "connectionToken": "SZyT2pHeOXXNaCrveIJx5A",
      "availableTransports": [
        {
          "transport": "WebSockets",
          "transferFormats": [
            "Text",
            "Binary"
          ]
        },
        {
          "transport": "ServerSentEvents",
          "transferFormats": [
            "Text"
          ]
        },
        {
          "transport": "LongPolling",
          "transferFormats": [
            "Text",
            "Binary"
          ]
        }
      ]
    }
    

    源码文档的描述中可以看出,如果在请求的时候,没有发送negotiateVersion这个参数,它会默认为0,且此时返回的数据中是没有connectionToken这个参数的。

    并且在连接websocket的时候,如果对id这个参数赋值的话,如果它是错误的,会提示你无法连接,但是如果你不传这个id,它其实是可以连接上的。

    连接websocket-->chatHub

    WebSockets传输是唯一的,因为它是全双工的,并且可以在单个操作中建立持久连接。结果,不需要客户端使用该POST [endpoint-base]/negotiate请求来预先建立连接。它还在其自己的帧元数据中包含所有必需的元数据。

    通过建立与WebSocket的连接来激活WebSocket传输[endpoint-base]。该可选的 id查询字符串值被用来识别附加到连接。如果没有id查询字符串值,则建立新连接。如果指定了参数,但没有与指定ID值的连接,404 Not Found则返回响应。收到此请求后,将建立连接,并且服务器将101 Switching Protocols立即通过WebSocket升级()进行响应,以准备发送/接收帧。WebSocket OpCode字段用于指示帧的类型(文本或二进制)。

    如果已经存在与端点连接关联的WebSocket连接,则不允许建立第二个WebSocket连接,并且将失败,并显示409 Conflict状态代码。

    建立连接时的错误通过返回500 Server Error状态码作为对升级请求的响应来处理。这包括初始化EndPoint类型的错误。未处理的应用程序错误会触发WebSocketClose框架,其原因码与规范中的错误相匹配(对于错误消息(例如消息过大或无效的UTF-8))。对于连接过程中的其他意外错误,将使用非1000 Normal Closure状态代码。

    jmeter配置

    1.negotitate请求

    2.打开websocket连接

    3.发送webscoket数据

    在SignalR中,总是要从客户端发送的第一帧是HandshakeRequest {“ protocol”:“ json”,“ version”:1}

    4.添加websocket心跳机制

    SignalR的心跳机制是底层自动发送的,而且客户端和服务端并不会构成实时响应,就类似于,服务端和客户端两者分别自己发送心跳,我们模拟一个客户端的发送心跳

    这个使用jmeter的Sampler-->websocket Single Write Sampler 添加即可,保持与websocket连接,发送内容为 {"type":6}

    5.其他

    • 基于SignalR的websocket在模拟测试发送消息的时候,都需要在后面添加一个特殊符号,我们可以从web页面F12中【NetWork】里抓取这个特殊符号。
    • jmeter中的websocket组件似乎针对广播模式的场景支持不太友好,因为广播模式下,客户端不知道什么时候会收到服务端的消息,或者说会一直收到服务端的消息(并发人数够多的时候),而如果此时没有读取websocket中的(通道中)的消息,可能会造成网路堵塞,然后测试用例就开始出现异常,从而出现连接断开

    不使用 SignalR 的 WebSocket

    微软官方也提供了不使用 SignalR 的 WebSocket的方法,有兴趣的小伙伴可以研究下:

    https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/websockets?view=aspnetcore-5.0

    其他参考

  • 相关阅读:
    测试 多线程 实现 callable 带返回值
    给定一个 hashMap 最终输出最大值的键
    正则判断输入的字符(英文、数字、空格、其他)的个数
    当返回值为json字符串时 如何获得其中的json数组
    thread run 和 start 的区别
    docker 构建dockerfile
    jsonp 跨域
    springsession 实现session 共享
    通过反射获得 spring 的 RequestMapping value值
    redis 集群搭建 以及 报错解决
  • 原文地址:https://www.cnblogs.com/seeyouethan/p/1_1.html
Copyright © 2011-2022 走看看