Nginx反向代理WebSocket(WSS)
1. WebSocket协议
WebSocket 协议提供了⼀种创建⽀持客户端和服务端实时双向通信Web应⽤程序的⽅法。作为HTML5规范的⼀部分,WebSockets简化了开发Web实时通信程序的难度。⽬前主流的浏览器都⽀持WebSockets,包括⽕狐、IE、Chrome、Safari以及Opera等,⽽且,越来越多的服务器应⽤框架也开始⽀持WebSockets。
要在企业产品中使⽤WebSockets,为满⾜⾼性能和⾼可⽤性,需要多个WebSocket服务器。负载均衡层需要⽀持WebSocket协议。Nginx 从1.3版起就开始⽀持WebSocket协议,⽽且可以担当WebSocket应⽤程序的反向代理以及实现负载均衡。
WebSocket协议和HTTP协议不同,但是WebSocket协议的握⼿和HTTP是兼容的,它使⽤HTTP的Upgrade协议头将连接从HTTP连接升级到WebSocket连接。这个特性使得WebSocket应⽤程序可以很容易地应⽤到现有的基础设施。例如,WebSocket应⽤可以使⽤标准的80和443 HTTP端⼝,因此可以通过现有的防⽕墙设施。
WebSockets应⽤程序会在客户端和服务器之间建⽴⼀个长连接,使得开发实时应⽤很容易。HTTP的Up
grade协议头机制⽤于将连接从HTTP连接升级到WebSocket连接,Upgrade机制使⽤了Upgrade协议头和Connection协议头。反向代理服务器在⽀持WebSocket协议⽅⾯⾯临着⼀些挑战。挑战之⼀是WebSocket是⼀个逐段转发(hop-by-hop)协议,因此当代理服务器拦截到来⾃客户端的Upgrade请求时,代理服务器需要将⾃⼰的Upgrade请求发送给后端服务器,包括适合的请求头。⽽且,由于WebSocket连接是长连接,与传统的HTTP端连接截然不同,故反向代理服务器还需要允许这些连接处于打开(Open)状态,⽽不能因为其空闲就关闭了连接。
NGINX⽀持WebSocket。对于NGINX将升级请求从客户端发送到后台服务器,必须明确设置Upgrade和Connection标题。
2. Nginx配置
Nginx通过在客户端和后端服务器之间建⽴隧道来⽀持WebSockets通信。为了让Nginx可以将来⾃客户端的Upgrade请求发送到后端服务器,Upgrade和Connection的头信息必须被显式的设置。
1)编辑f,在http区域内⼀定要添加下⾯配置:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
map指令的作⽤:
该作⽤主要是根据客户端请求中$http_upgrade 的值,来构造改变$connection_upgrade的值,即根据变量$http_upgrade的值创建新的变量$connection_upgrade,
创建的规则就是{}⾥⾯的东西。其中的规则没有做匹配,因此使⽤默认的,即 $connection_upgrade 的值会⼀直是 upgrade。然后如果 $http_upgrade为空字符串的话,
那值会是 close。
2)编辑vhosts下虚拟主机的配置⽂件,在location匹配配置中添加如下内容:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
⽰例如下:
upstream socket.kevin {
hash $remote_addr consistent;
server 10.0.12.108:9000;
server 10.0.12.109:9000;
}
location / {
proxy_pass socket.kevin/;
proxy_set_header Host $host:$server_port;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
3)可能会出现跨域问题,server区块填写以下跨域配置即可
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-
Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
⼀旦我们完成以上设置,Nginx就可以处理WebSocket连接了
设置代理使⽤的HTTP协议版本。默认使⽤的版本是1.0,⽽1.1版本则推荐在使⽤keepalive连接时⼀起使⽤。
因为http1.0不⽀持keepalive特性,当没有使⽤http1.1的时候,后端服务会返回101错误,然后断开连接。
map的作⽤
1.map的作⽤主要是根据客户端请求中 $http_upgrade 的值,来构造改变 $connection_upgrade 的值,即根据变量 $http_upgrade 的值创建新的变量 $connection_upgrade,创建的规则就是 {} ⾥⾯的东西,上图代码中(第⼀个标记点)的规则没有做匹配,因此使⽤默认的,即$connection_upgrade 的值会⼀直是 upgrade。然后如果 $http_upgrade为空字符串的话,那值会是 close。
HTTP的Upgrade协议头
HTTP的Upgrade协议头机制⽤于将连接从HTTP连接升级到WebSocket连接,Upgrade机制使⽤了Upgrade协议头和Connection协议头;为了让Nginx可以将来⾃客户端的Upgrade请求发送到后端服务器,Upgrade和Connection的头信息必须被显式的设置。
3. Nginx代理WebSocket保持长连接的⽅案
现象描述:⽤nginx反代代理某个业务,发现平均1分钟左右,就会出现webSocket连接中断,然后查看了⼀下,是nginx出现的问题。
产⽣原因:nginx等待第⼀次通讯和第⼆次通讯的时间差,超过了它设定的最⼤等待时间,简单来说就是超时!
解决⽅法1
其实只要配置f的对应localhost⾥⾯的这⼏个参数就好
proxy_connect_timeout;
proxy_read_timeout;
proxy_send_timeout;
解决⽅法2
发⼼跳包,原理就是在有效地再读时间内进⾏通讯,重新刷新再读时间
http {
如何设置代理服务器server {
location / {
root html;
index index.html index.htm;
proxy_pass webscoket;
proxy_http_version 1.1;
proxy_connect_timeout 4s; #配置点1
proxy_read_timeout 60s; #配置点2,如果没效,可以考虑这个时间配置长⼀点
proxy_send_timeout 12s; #配置点3
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}
关于上⾯配置2的解释
这个是服务器对你等待最⼤的时间,也就是说当你webSocket使⽤nginx转发的时候,⽤上⾯的配置2来说,如果60秒内没有通讯,依然是会断开的,所以,你可以按照你的需求来设定。⽐如说,我设置了10分钟,那么如果我10分钟内有通讯,或者10分钟内有做⼼跳的话,是可以保持连接不中断的,详细看个⼈需求
WebSocket与Socket的关系
- Socket其实并不是⼀个协议,⽽是为了⽅便使⽤TCP或UDP⽽抽象出来的⼀层,是位于应⽤层和传输控制层之间的⼀组接⼝。当两台主机通信时,必须通过Socket连接,Socket则利⽤TCP/IP协议建⽴TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。
- WebSocket就像HTTP⼀样,则是⼀个典型的应⽤层协议。
总的来说:Socket是传输控制层接⼝,WebSocket是应⽤层协议。
参考:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论