最近ipc通过websocket与server进行通行,经过无法通过nginx进行反向代理,只有直连nodejs端口。而且部署到阿里云用了slb之后同样存在该问题。因为部署为了规避风险不宜暴露nodejs端口,所以尝试解决这个问题。
在实际的生产环境中,要求多个WebSocket服务器必须具有高性能和高可用,那么WebSocket协议就需要一个负载均衡层,NGINX从1.3开始支持WebSocket,其可以作为一个反向代理和为WebSocket程序做负载均衡。
配置nginx 即支持websocket的反向代理。使用这两句开启nginx对websocket的支持功能:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
sample:
server {
listen 80;
location / {
proxy_pass http://localhost:6000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
PS:在学习过程了解到有种情况websocket连上nginx会断开的问题可能与 nginx这个参数配置有关proxy_read_timeout
阿里云SLB 支持http下的websocket,之所以前面不行。
选择的4层tcp下的监听。-只解析到4层,负载均衡服务器与client三次握手之后就会和后端服务器建立连接。
即:根本不会到http层。而websocket 的握手就必须到http才能实现。
当改成7层http的监听就可以成功实现代理了。
当大量客户端从外部访问VIP地址时,负载均衡设备将这些报文请求根据负载均衡算法,将流量均衡的分配给后台服务器以平衡各个服务器的负载压力,避免在还有服务器压力较小情况下其他服务达到性能临界点出现运行缓慢甚至宕机情况,从而提高服务效率和质量,因此对客户端而言,RS(后端服务器)的IP地址即是负载均衡设备VIP地址(对外开放的地址),真正的RS服务器IP地址对于客户端是不可见的。
四层SLB:配置APV设备上服务类型为tcp/udp,APV设备将只解析到4层,APV与client三次握手之后就会和RS建立连接。
七层SLB:配置APV设备服务类型为http/ftp/https等,APV设备将解析报文到7层,在APV设备与client三次握手之后,只有收到对应七层报文,才会跟RS建立连接。
流程:
1 client向SLB发起请求建立链接 (ip1 6000-> ip2 80。
2 SLB 会以自身地址与client 建立TCP连接。(3次握手)
3 解析到http请求(7层)后根据负载均衡算法与server建立链接。(ip2 xx -> ip3 7000)端口号为ip下的随机号。
4 server以自身地址与ip2 xx建立连接。(3次握手)
5 SLB 将从client收到的报文 源ip改为ip2 xx 发给server。
6 server收到报文后 用自身地址(ip3 7000) 想SLB(ip2 xx)进行回复。
7 SLB收到server的报文,将报文原地址改为SLB对外地址(ip 80)发回client(ip1 6000)
PS:四层和七层负载均衡的区别在1-4步,4层负载均衡会在tcp建立连接后就会与server建立链接。而不是在3步中解析到7层才建立链接。这也是为什么ALI云四层无法支持websocket的原因:Websocket 发过去的报文在SLB 根本(websocket握手是建立http基础上的)就无法握手建立链接。
参考文章:
http://blog.csdn.net/u010192132/article/details/44095839
websocket通俗科普原文链接:
https://www.zhihu.com/question/20215561
WebSocket 通过第一个 HTTP request 建立了 TCP 连接之后,之后的交换数据都不需要再发 HTTP request了的一个持久化的协议(相对于HTTP这种非持久的协议来说)。
首先Websocket是基于HTTP协议的,或者说借用了HTTP的协议来完成一部分握手。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
这段类似HTTP协议的握手请求中,多了几个东西。
Upgrade: websocket
Connection: Upgrade
这个就是Websocket的核心了,告诉Apache、Nginx等服务器:client发起的是Websocket协议,需要支持支持webSocket的location 来进行处理。(所以 nginx需要配置1节中的那两句话,否者无法握手)
Sec-WebSocket-Key 是一个Base64 encode的值这个是浏览器随机生成的,用于验证server端是不是支持websocket的接口。
Sec_WebSocket-Protocol 是一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议。
Sec-WebSocket-Version 是告诉服务器所使用的Websocket Draft(协议版本)
然后服务器会返回下列东西,表示已经接受到请求, 成功建立Websocket啦!
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
这里开始就是HTTP最后负责的区域了,告诉客户,我已经成功切换协议啦
Upgrade: websocket
Connection: Upgrade
告诉客户端即将升级的是Websocket协议
Sec-WebSocket-Accept这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key
Sec-WebSocket-Protocol 则是表示最终使用的协议。
ajax轮询 需要服务器有很快的处理速度和资源。(速度)
long poll 需要有很高的并发,也就是说同时接待客户的能力。(场地大小)
而一般应用框架是 client -> nginx -> server
作为代理的nginx处理速度是非常快的,但除了真正的数据部分外,服务器和客户端还要大量交换 HTTP header,信息交换效率很低。
优点1:
WebSocket 通过第一个 HTTP request 建立了 TCP 连接之后,之后的交换数据都不需要再发 HTTP request了,使得这个长连接变成了一个真.长连接。变成了tcp长连接后就解决了传统的http反复请求导致处理大量的http head对nginx造成的压力。
优点2:
Websocket只需要一次HTTP握手,所以说整个通讯过程是建立在一次连接/状态中,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请求,这样就解决了nginx要反复解析HTTP协议,还要查看identity info的信息。