前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SignalR 开发到生产部署避坑指南

SignalR 开发到生产部署避坑指南

作者头像
有态度的马甲
修改2021-11-18 15:10:36
1.2K0
修改2021-11-18 15:10:36
举报
文章被收录于专栏:精益码农精益码农
前天倒腾了一份[SignalR在react/

01

SignalR默认要协商传输方式

SignalR 默认要求协商传输方式[1]

不管是.NET客户端还是JavaScript客户端,构建连接时都存在一个默认配置:SkipNegotiation=fasle,负负得正就等于要求协商,这个默认配置的完整含义是 建立SignalR连接时,客户端要求协商传输方式

对应产生下图:

小技巧(嬉笑脸

):如果你确定你的网络环境能稳定的走websocket传输, 为了快速建立实时通信,可跳过协商请求(设置SkipNegotiation=true), 毕竟每次刷新页面,react组价都会重新加载,重新协商再传输 费时费力。

代码语言:javascript
复制
 const connection = new HubConnectionBuilder()
        .withUrl(process.env.REACT_APP_APIBASEURL+"realtime", {
          skipNegotiation: true,  
          transport: HttpTransportType.WebSockets
        })
        .withAutomaticReconnect()
        .withHubProtocol(new JsonHubProtocol())
        .configureLogging(LogLevel.Information)
        .build();

注意:SkipNegotiation=true,仅限于客户端的传输方式指定为 websocket, 其他方式均会报错。

02

SignalR传输协商是fetch请求

跟ajax一样,fetch请求[2]也是浏览器脚本的一种,所以很明显也会涉及跨域,标准的CORS方案依然对其有效。

http://localhost:9598/realtime/negotiate?negotiateVersion=1 Post请求 有自定义的请求头 X-Requested-With, X-Signalr-User-Agent

很明显,这又会触发预检Option请求

故你还需要在使用 CORS Middleware时允许这几个自定义请求头。

代码语言:javascript
复制
 // 下面是Go github.com/rs/cors package 支持CORS的代码
  
 c := cors.New(cors.Options{
   // AllowedOrigins:   []string{"http://localhost:3000","http://rosenbridge.17usoft.com"},
    AllowOriginFunc: func(origin string) bool {
      return true
    },
    AllowedMethods:   []string{"POST", "GET", "OPTIONS", "PUT", "DELETE"},  // 下面要加上signalr传输协商要用到的自定义请求头
    AllowedHeaders:   []string{"Content-Type", "x-requested-with", "x-signalr-user-agent"},
    AllowCredentials: true,
    Debug:            cfg.Log.Debug,
 })

03

WebSocket请求也有同源限制

ws://localhost:9598/realtime?id=aoSD_WZhqbRfPyXVTYsHig==

WebSocket也有同源限制[3] (无奈脸

),但是标准的CORS对其无效,因为CORS解决是HTTP脚本请求的跨域问题,WebSocket说到底不算http协议。

浏览器依旧会为我们携带Origin标头,所以服务端需要验证这些标头,确保只允许来自预期来源的WebSocket。

代码语言:javascript
复制
// 以下是.NET Core 针对websocket同源限制做出的跨域配置

var webSocketOptions = new WebSocketOptions()
{
    KeepAliveInterval = TimeSpan.FromSeconds(120),
};
webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");

app.UseWebSockets(webSocketOptions);

btw, 我使用的GO SignalR库不支持WebSocket跨域, 我提了一个PR[4], 已经成功合并,(兴奋脸

),这是我首次向开源项目提PR且获得通过的项目。

04

部署生产,需要nginx支持

按照默认配置,一般会先协商,再使用websocket传输。

部署到生产之后,协商后优先使用WebSocket模式, 但是传输失败了, 自动切换为服务器发送事件SSE模式,传输成功。

浏览器开发者工具看不出啥端倪, 使用Fiddler抓包发现 400 状态码

网上搜索了一下,可能是生产的nginx不识别websocket标头。在nginx配置里面添加如下配置就可以了。

代码语言:javascript
复制
location / {
     proxy_http_version 1.1; 
     proxy_set_header Upgrade $http_upgrade;                
     proxy_set_header Connection "upgrade";    
}

以上是马甲哥整理的SignalR从开发到部署的闭坑指南,因为微信公众号内容发布后不方便重新编辑,后续有更多闭坑技能,会同步到大家喜闻乐见的博客园马甲哥[5]。

还没完, 因为本文是零散的闭坑指南, 文中点出的坑位其实都有相关技能点,感兴趣的童靴可以认真阅读下面给出的相关推荐(真诚脸

实时通信技术大乱斗

.NET WebSocket 核心原理初体验

.NET gRPC核心功能初体验

SignalR在React/Go技术栈的实践

对CORS OPTIONS预检请求的一些思考

程序员应对浏览器同源策略的姿势

引用链接

[1] SignalR 默认先协商: https://docs.microsoft.com/en-us/aspnet/core/signalr/configuration?view=aspnetcore-5.0&tabs=dotnet [2] fetch请求: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch [3] WebSocket也有同源限制: https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/websockets?view=aspnetcore-5.0 [4] PR: https://github.com/philippseith/signalr/pull/75 [5] 博客园马甲哥: https://www.cnblogs.com/JulianHuang/p/15434137.html

快完了,号外号外:

  1. 本文内容和制图均为原创,文章永久更新地址请参阅左下角原文,如对您有所帮助,请一键三连,激浊扬清,方便的话置一个星标 ~。。~。
  2. 关注本号,后台回复【pdf】,送你号主征战多年的经典技术PDF:大前端、.net、Go、云原生、数据库,童嫂无欺,回复【码甲哥】,加我好友。
  3. 关注本公众号的5000+筒靴们应该都知道,本号一直不遗余力的输出原创技术、职场心得,内容说不上什么耳目一新、醍醐灌顶,但号主的技能点一直在进化,本次建立了一个[码甲哥高质量交流群],希望能和童鞋面对面成长(真诚脸)。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 精益码农 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云开发 CLI 工具
云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档