2653885 发表于 2017-12-23 12:43:38

阿里云负载不支持 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_namesingalr
.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

页: [1]
查看完整版本: 阿里云负载不支持 WebSocket 协议与 WSS 和 Nginx 配置问题