SingnalR 从开发到生产部署闭坑指南
前天倒腾了一份[SignalR在react/go技术栈的实践], 步骤和思路大部分是外围框架的应用, 今天趁热打铁, 给一个我总结的SignalR避坑指南。
1.SignalR 默认协商
不管是.NET客户端还是JavaScript客户端,构建连接时都存在一个默认配置:SkipNegotiation=fasle,负负得正就等于要求协商,这个默认配置的完整含义是 建立SignalR连接时,客户端要求协商传输方式。
对应产生下图:

小技巧:如果你确定你的网络环境能稳定的走websocket传输, 为了快速建立实时通信,可跳过协商请求(设置SkipNegotiation=true), 毕竟每次刷新页面,react组价都会重新加载,重新协商再传输 费时费力。
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, 其他方式均会报错。
2.SignalR 传输协商是fetch请求
跟ajax一样,fetch请求也是浏览器脚本的一种,所以很明显也会涉及跨域,标准的CORS方案依然对其有效。
http://localhost:9598/realtime/negotiate?negotiateVersion=1
Post请求
有自定义的请求头 X-Requested-With, X-Signalr-User-Agent
很明显,这又会触发预检Option请求

故你还需要在使用 CORS Middleware时允许这几个自定义请求头。
// 下面是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,
})
3. websocket也有同源限制
ws://localhost:9598/realtime?id=aoSD_WZhqbRfPyXVTYsHig==
WebSocket也有同源限制,但是标准的CORS对其无效,因为CORS解决是HTTP脚本请求的跨域问题,WebSocket说到底不算http协议。
浏览器依旧会为我们携带Origin标头,所以服务端需要验证这些标头,确保只允许来自预期来源的WebSocket。
// 以下是.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, 已经成功合并,兴奋,这是我首次向开源项目提MR且获得通过的项目。
不仅signalr协商请求需要 CORS, 真正传输的websocket协议也有跨域一说,我使用了一个库,没有做到cors,我提了一个mr,成功合并。
4. 部署生产后,需要nginx支持
按照默认配置,一般会先协商,再使用websocket传输。
部署到生产之后,协商后优先使用WebSocket模式, 但是传输失败了, 自动降级为服务器发送事件SSE模式,传输成功。

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

网上搜索了一下,可能是生产的nginx不识别websocket标头。
在nginx配置里面添加如下配置就可以了
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
关注本公众号的5000+筒靴们应该都知道,本号一直不遗余力的输出原创技术、职场心得,内容说不上什么耳目一新、醍醐灌顶,但号主的技能点一直在进化,本次建立了一个[码甲哥高质量交流群],希望能和童鞋面对面成长(真诚脸图片)。

SingnalR 从开发到生产部署闭坑指南的更多相关文章
- RabbitMQ生产部署指南
像RabbitMQ这样的数据服务通常有许多可调参数.一些配置对开发有很大的意义,但并不适合生产,本指南旨在为此提供帮助 虚拟主机 例如,在单租户环境中,当您的RabbitMQ集群专门为生产中的单个系统 ...
- Linux 桌面玩家指南:18. 使用 Docker 隔离自己的开发环境和部署环境
特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...
- 2016/5/6 thinkphp ①框架 ② 框架项目部署 ③MVC模式 ④控制器访问及路由解析 ⑤开发和生产模式 ⑥控制器和对应方法创建 ⑦视图模板文件创建 ⑧url地址大小写设置 ⑨空操作空控制器 ⑩项目分组
真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分困难,代码风格不一样) 项目稳 ...
- 一个gulp用于开发与生产的示例
gulp是一款流行的前端构建工具,可以帮我们完成许多工作:监听文件修改.刷新浏览器.编译Less/Scss.压缩代码.添加md5.合并文件等.gulp的配置和使用特别简单,学习gulp过程中顺便写了一 ...
- webpack开发与生产环境配置
前言 作者去年就开始使用webpack, 最早的接触就来自于vue-cli.那个时候工作重点主要也是 vue 的使用,对webpack的配置是知之甚少,期间有问题也是询问大牛 @吕大豹.顺便说一句,对 ...
- kettle-数据源配置化-开发、生产采用不同配置
数据etl常用工具kettle. 1.说明: kettle-数据源配置化:是指kettle的数据源连接信息全部或者部分从配置文件中读取(如果是数据库的资源库,那么资源库也可以配置化). 2.优点: 1 ...
- spring boot--日志、开发和生产环境切换、自定义配置(环境变量)
Spring Boot日志常用配置: # 日志输出的地址:Spring Boot默认并没有进行文件输出,只在控制台中进行了打印 logging.file=/home/zhou # 日志级别 debug ...
- 免费开源《OdooERP系统部署架构指南》试读:第一章 Odoo架构概述
文/开源智造联合创始人老杨 本文来自<OdooERP系统部署架构指南>的试读章节.书籍尚未出版,请勿转载.欢迎您反馈阅读意见. 从web浏览器到PostgreSQL,多层与其他层交互以处理 ...
- Laravel本地环境搭建:Homestead开发环境的部署
Laravel框架在php开发过程是不断进行优化的,当然也包括了本地环境的开发,下面我们就来具体看看laravel框架中的Homestead 开发环境的部署内容. 首先白以下几个概念 VirtualB ...
随机推荐
- java基础之ThreadLocal
早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序.Thr ...
- vue 路由视图,router-view嵌套跳转
实现功能:制作一个登录页面,跳转到首页,首页包含菜单栏.顶部导航栏.主体,标准的后台网页格式.菜单栏点击不同菜单控制主体展示不同的组件(不同的页面). 配置router-view嵌套跳转需要准备两个主 ...
- PPPoE技术白皮书(H3C)
PPPoE技术白皮书 关键词:PPP,Ethernet,PPPoE 摘要:PPPoE是一种通过一个远端接入设备为以太网上的主机提供接入服务,并可以对接入的每个主机实现控制和计费的技术.本文介绍了PPP ...
- 分组概念&贪婪与懒惰
分组概念&贪婪与懒惰 1.分组 2.贪婪和懒惰 3.懒惰 4.处理选项 5.实例:百度搜索结果页面源码中获取当前页的10个标题 5.1页面源码分析规律 5.2正则表达式,匹配出10个标题 这是 ...
- ☕【JVM技术指南】「JVM总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【下部】
承接上文 (完结撒花1-52系列)[JVM技术指南]「JVM总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"[上部] 并行收集器 并行收集器(也称为吞吐量收集器)是类似 ...
- CommonsCollections3 反序列化利用链分析
InstantiateTransformer commons-collections 3.1 中有 InstantiateTransformer 这么一个类,这个类也实现了 Transformer的t ...
- Docker系列(4)- run的流程和docker原理
回顾HelloWorld流程 底层工作原理 Docker是怎么工作的? Docker是一个Client-Server结构的系统,Docker的守护进程运行在宿主机上.通过Socket从客户端访问 Do ...
- JDK1.8源码(三)——java.lang.String类
一.概述 1.介绍 String是一个final类,不可被继承,代表不可变的字符序列,是一个类类型的变量.Java程序中的所有字符串字面量(如"abc")都作为此类的实例实现,&q ...
- python学习笔记(九)-函数2
交换两个变量的值 a = 2 b = 1 b = 1 a = 2 #方式一: b,a = a,b #交换两个变量的值 print(a,b) #方式二: a = a + b #3 b = a - b # ...
- LR11自带网站
LR自带的飞机订票系统 启动服务:安装路径\HP\LoadRunner\WebTours下的StartServer.bat 打开网页:地址 http://127.0.0.1:1080/WebTour ...