翼度科技»论坛 编程开发 .net 查看内容

.Net 6 SignalR 实际业务开发中遇到的问题及解决办法

11

主题

11

帖子

33

积分

新手上路

Rank: 1

积分
33
一、SiganlR 使用的协议类型


  • 1.websocket即时通讯协议
  • 2.Server-Sent Events(SSE)服务器事件
  • 3.longpolling 长轮询。
如果客户端开启协商,会按顺序选择可兼容的协议。(默认开启协议协商)
如果客户端禁用协商,只能websocket协议。
二、连接过程


  • 1.http 协议协商过程 客户端向服务器发http请求连接,询问服务器支持什么协议。
    服务端返回支持的协议类型,并分配ConnectionId。(未禁用协议协商时有)
  • 2.ws 客户端确认协议后发送ws请求,建立连接。
三、身份认证


  • websocket协议 无请求报文头headers,token只能放 QueryString 中,一般参数名定为 access_token。
  • 在 Hub中引入身份认证服务,Hub OnConnectedAsync()中,即建立连接时,通过身份认证服务解析token是否合法并拿到用户信息。
四、集群、分布式部署问题

问题1. 多个服务器集群环境,客户端协商过程,可能请求到不同服务器。

在协商过程,如果有AB两个服务器集群
客户端第一次http请求A,A服务器记录了客户端连接信息上下文。
客户端第二次ws连接发送到B服务器,而B服务器没有客户端连接信息上下文,就出错了。
方式1. 粘性会话

网关服务器 或 负载均衡服务器 进行配置,把来自同一个客户端的请求都转发给同一台服务器。

  • 优点:兼容性最好,客户端按兼容性依次选择协议
  • 缺点:公网ip没办法平均分配,很难控制。
方式2. 禁用协商

客户端连接时设置禁用协商,连接时仅一次ws请求。

  • 缺点:只能适用于兼容websocket的浏览器 只能使用websocket协议,无法使用 sse  和 longpolling
问题2. 集群环境 消息不能跨服务器连接发送。

A服务器向全部连接发消息,只能发送到连接A服务器的客户端,不能发送给连接到B服务器的客户端。

  • 解决办法:引入 Microsoft.AspNetCore.SignalR.StackExchangeRedis 包,注入分布式SignalR服务到DI中。
    作用:在多个服务器实例之间共享消息和连接状态。确保跨服务器实例的连接同步和消息传递。
    1. services.AddSignalR(o =>
    2.   {
    3.       o.EnableDetailedErrors = true;//详细异常信息
    4.       o.HandshakeTimeout = TimeSpan.FromSeconds(30);//握手超时时间
    5.   }).AddStackExchangeRedis("{redis连接字符串}", opt =>
    6.   {
    7.       opt.Configuration.ChannelPrefix = "{RedisKey前缀}";
    8.   });//分布式 SignalR 消息
    复制代码
问题3. 在后台任务中使用Hub推送消息。


  • 1.建立连接,从token中拿到用户信息。

    • 缓存: 用户id - [连接id集合]
    • 缓存: 连接id - 用户id

  • 2.断开连接,从缓存中移除 当前连接id
  • 3.后台任务

    • 注入分布式SignalR服务
    • 注入Hub服务
    • 业务中拿到要接收消息的 用户id集合
    • 从缓存中找到对应的 全部连接id
    • 调Hub向连接id推送SignalR消息


来源:https://www.cnblogs.com/kong-ming/archive/2023/09/01/17672570.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具