阿里云负载不支持 WebSocket 协议与 WSS 和 Nginx 配置问题
WebSocket 是 HTML5 下一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的。它与HTTP一样通过已建立的TCP连接来传输数据,但是它和HTTP最大不同是:
- WebSocket是一种双向通信协议。在建立连接后,WebSocket服务器端和客户端都能主动向对方发送或接收数据,就像Socket一样;
- WebSocket需要像TCP一样,先建立连接,连接成功后才能相互通信。
WebSocket 连接本质上是一个 TCP 连接,比较轮询在数据传输的稳定性和数据传输量的大小方面,具有很大的性能优势。
浏览器请求
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: null
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
客户端发起的WebSocket连接报文类似传统HTTP报文,Upgrade:websocket参数值表明这是WebSocket类型请求,Sec-WebSocket-Key是WebSocket客户端发送的一个 base64编码的密文,要求服务端必须返回一个对应加密的Sec-WebSocket-Accept应答,否则客户端会抛出Error during WebSocket handshake错误,并关闭连接。
在请求中的Sec-WebSocket-Key是随机的,服务器端会用这些数据来构造出一个SHA-1的信息摘要。把Sec-WebSocket-Key加上一个魔幻字符串258EAFA5-E914-47DA-95CA-C5AB0DC85B11。使用 SHA-1 加密,之后进行 BASE-64编码,将结果作为 Sec-WebSocket-Accept 头的值,返回给客户端;WebSocket 先是通过 HTTP 建立连接, 然后通过 101 状态码, 表示切换协议,在配置里是 Upgrade。
服务器回应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Origin: null
Sec-WebSocket-Location: ws://example.com/
Sec-WebSocket-Accept 的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,HTTP/1.1 101 Switching Protocols表示服务端接受WebSocket协议的客户端连接,经过这样的请求-响应处理后,两端的WebSocket连接握手成功, 后续就可以进行TCP通讯了。用户可以查阅WebSocket协议栈了解WebSocket客户端和服务端更详细的交互数据格式。
浏览器兼容性
最新的主流浏览器对WebSocket支持良好:
- Chrome 4+
- Firefox 4+
- Internet Explorer 10+
- Opera 10+
- Safari 5+
我们在阿里云启用全站 HTTPS 后,我们发现阿里云 webscoket 通信报错 400 Bad Request 错误,开始以为是启用HTTPS的问题,后面发现阿里云的负载均衡(LB)根本就不支持 ws 协议(https://help.aliyun.com/document_detail/63421.html?spm=5176.doc63420.6.714.hC3lA2),Google 了一番,决定使用 nginx 代理。
备注:阿里 ws 与 http2 支持情况 https://yq.aliyun.com/articles/277584?spm=5176.10695662.1996646101.searchclickresult.2a8d761c2PJag1
Request URL:wss://singalr.xxx.cn/signalr/connect?transport=webSockets&clientProtocol=1.5&connectionToken=xmpmOB19Q6d7X32GFEP7lTFm7DPSJIcRALZOxbASrpogN5MPTTBafipQsNBs0x5J7wvUm5QI8e1iViqETc9Q8%2FGHCLZo5GhJsXYRWmOzsICh5LDyQDGnAsRSC3GvBMsQ&connectionData=%5B%7B%22name%22%3A%22signalrpushhub%22%7D%5D&tid=9
Request Method:GET
Status Code:400 Bad Request Response Headers
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:https://xxx.cn
Cache-Control:no-cache
Connection:keep-alive
Content-Type:text/html
Date:Wed, 17 May 2017 02:09:56 GMT
Expires:-1
Pragma:no-cache
Transfer-Encoding:chunked
X-AspNet-Version:4.0.30319
X-Content-Type-Options:nosniff
X-Powered-By:ASP.NET Response Headers
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:no-cache
Connection:Upgrade
Cookie:_pms_session=5d0gqrezzfgvivj2b4oaecy3; acw_tc=AQAAAMvoFF/VeQoAJkNKfD0idg5CQvGL
Host:singalr.xxx.cn
Origin:https://p2.xxx.cn
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:V2NZvyJw/CJtAdn68xDZWA==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36 Query String Parameters
transport:webSockets
clientProtocol:1.5
connectionToken:xmpmOB19Q6d7X32GFEP7lTFm7DPSJIcRALZOxbASrpogN5MPTTBafipQsNBs0x5J7wvUm5QI8e1iViqETc9Q8/GHCLZo5GhJsXYRWmOzsICh5LDyQDGnAsRSC3GvBMsQ
connectionData:[{"name":"signalrpushhub"}]
tid:9
WebSocket 的 Nginx 配置
开始以为是 HTTPS 443 监听的问题,后面修发现HTTP下ws协议也不可以,咨询了一番,最后发现是阿里云负载均衡不支持 ws 协议的问题。单独把 signalr 的服务端使用 nginx 代理负载 ,其他服务器还是使用阿里云的负载
upstream singalr {
server 192.168.1.5;
server 192.168.1.4;
}
server {
listen 443 ssl;
server_name singalr.com;
#charset koi8-r;
#access_log logs/host.access.log main;
ssl on;
ssl_certificate /etc/ssl/private/xxxx.pem;
ssl_certificate_key /etc/ssl/private/xxx.key;
location / {
proxy_pass http://singalr;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
REFER:
http://nginx.org/en/docs/http/websocket.html
https://socket.io/
https://github.com/SignalR/SignalR
https://github.com/aspnet/SignalR
http://blog.mixu.net/2011/08/13/nginx-websockets-ssl-and-socket-io-deployment/
https://docs.microsoft.com/en-us/aspnet/signalr/overview/performance/scaleout-with-redis
http://www.ruanyifeng.com/blog/2017/05/websocket.html
WebSocket 实现原理
http://zeeyang.com/2017/07/02/websocket/
https://www.qcloud.com/document/product/214/4150
https://www.zhihu.com/question/20215561
阿里云负载不支持 WebSocket 协议与 WSS 和 Nginx 配置问题的更多相关文章
- 阿里云全站加速DCDN全面支持WebSocket协议
WebSocket协议可以为网站和应用提供真正的双向通信,具有控制开销.保持连接状态.更强实时性.更好的压缩效果等优点,是当下低延时应用最常采用的一种技术协议.为了更好的满足客户在实时通讯场景下的加速 ...
- 使用阿里云负载均衡遭遇的http重定向https的问题
昨天解决了在阿里云负载均衡上部署https证书的问题(详见一个空行引起的阿里云负载均衡上部署https证书的问题),并完成了部署,负载均衡的监听配置是这样的: 用户与负载均衡之间走https协议,负载 ...
- 阿里云 负载均衡 HTTP转HTTPS
一.相关文档 1.证书服务 2.简单路由-HTTP 协议变为 HTTPS 协议 二.阿里云操作界面 1.云盾证书服务管理控制台(查询CA证书服务) 2.负载均衡管理控制台 三.相关文档 1.Syman ...
- 一个空行引起的阿里云负载均衡上部署https证书的问题
今天在阿里云上购买了WoSign的https证书,在证书签发后,在控制台下载证书文件,一共有2个文件,一个是.key文件(私钥文件),一个是.pem文件(证书文件). 然后在阿里云负载均衡“证书管理” ...
- 阿里云负载均衡SSL证书配置
阿里云负载均衡SSL证书 转载请注明地址:http://www.cnblogs.com/funnyzpc/p/8908461.html 好久了呢,距上篇博客的这段时间中:考试.搬家.工作赶工.业务考察 ...
- 阿里云负载均衡SSL证书配置(更新)
阿里云负载均衡及应用防火墙SSL证书配置 转载请注明地址:http://www.cnblogs.com/funnyzpc/p/8908461.html 好久了呢,距上篇博客的这段时间中:考试.搬家.工 ...
- 阿里云服务器Linux CentOS安装配置(八)nginx安装、配置、域名绑定
阿里云服务器Linux CentOS安装配置(八)nginx安装.配置.域名绑定 1.安装nginx yum -y install nginx 2.启动nginx service nginx star ...
- 阿里云负载均衡配置https记录
配置前端协议是443,后端是80 问题1记录: 例如访问https://www.xxx.com,在后端服务器上面获取是http还是https请求协议实际上是http: 因为我们先请求负载均衡,负载均衡 ...
- 【阿里云IoT+YF3300】2.阿里云IoT云端通信Alink协议介绍
如果单单只有MQTT协议,也许很难支撑起阿里这个IoT大厦.Alink协议的出现,不仅仅是数据从传感端搬到云端,它就如基因图谱,它勾画了一个大厦的骨架,有了它,才有了IoT Studio,才有了大数据 ...
随机推荐
- Arria10中PHY的时钟线结构
发送器时钟网络由发送器PLL到发送器通道,它为发送器提供两种时钟 高速串行时钟——串化器的高速时钟 低速并行时钟——串化器和PCS的低速时钟 在绑定通道模式,串行和并行时钟都是由发送器的PLL提供给发 ...
- MySQL中@变量的妙用
背景需求:如下图所示,需要将下面为空的字段值,填充为第一行所示的值 第一次处理失败了 第二次使用成功 使用的SQL语句如下: set @tmp_var=''; select b.id,b.table_ ...
- 差值的再议-Hermite差值
1. 插值法 插值法又称“内插法”,是利用函数f (x)在某区间中已知的若干点的函数值,作出适当的特定函数,在区间的其他点上用这特定函数的值作为函数f (x)的近似值,这种方法称为插值法. 如果这特定 ...
- nodeclub config
配置文件,本来想着分成好几个文件,放在一个文件夹中,后来觉得也没必要,原因是,配置文件看一遍也就记住了,分开反而显得繁琐,注释写清楚就好. // 路径模块 var path = require('pa ...
- Android之TextView灵活使用
Android之TextView灵活使用 在项目中有无遇到过这样一种程况,例如文字"王明今年10岁了", 但是数字10是从网络返回的数据, 而你又想把这个文字写在xml中, 过往我 ...
- hive sql 查询一张表的数据不在另一张表中
有时,我们需要对比两张表的数据,找到在其中一张表,不在另一张表中的数据 hql 如下: SELECT * FROM (SELECT id FROM a WHERE dt = '2019-03-17' ...
- Linux-帮助与基本命令
1.获取命令帮助 Linux中的命令按可分类shell内嵌命令.外部命令,获取命令帮助信息前需要区分命令类型. 1.1 type - 查看命令类型 [root@VM_0_171_centos ~]# ...
- 路由其实也可以很简单-------Asp.net WebAPI学习笔记(一)
MVC也好,WebAPI也好,据我所知,有部分人是因为复杂的路由,而不想去学的.曾经见过一位程序猿,在他MVC程序中,一切皆路由,url中是完全拒绝"?"和“&”.对此,我 ...
- VS动态修改App.config中遇到的坑(宿主进程问题)
昨天遇到了很奇怪的一个bug,具体描述如下: 这个系统是c/s架构的针对多个工厂做的资材管理系统,由于有很多个工厂,每个工厂都有自己的服务器.所以需要动态的改变连接字符串去链接不同的服务器. 由于这个 ...
- WPF自定义Window窗体样式
资源文件代码: <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation ...