nginx-8 WebSocket代理
2019-03-27 本文已影响0人
苍老的小孩_a1fe
使用HTTP/1.1协议中的protocol_switch
机制,可以将客户端与服务器的连接协议由HTTP/1.1升级为WebSocket。
HTTP协议中的 hop-by-hop 头部
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade
只对单个传输级连接有效,不存储于缓存,可以由代理服务器转发。
HTTP method 之 CONNECT
CONNECT https://www.baidu.com HTTP/1.1
客户端告诉代理服务器,替我访问https://www.baidu.com,并将结果返回给我。
因为Upgrade
是一个hop-by-hop头部,所以不能直接从客户端传递给被代理的服务器。使用正向代理时,客户端可以CONNECT
方法回避这个问题。对于反向代理却回避不了,因为客户端并不知道代理服务器的存在,更不知道请求需要在代理服务器上特殊处理。
版本1.3.13之后,nginx实现了一种特殊操作模式:如果被代理的服务器返回带有101状态码的响应,并且客户端通过请求中的Upgrade
请求protocol_switch
,则允许在客户机和被代理的服务器之间设置隧道。
正如上面所说,作为hop-by-hop
头部,Upgrade
和Connection
不能从客户端直接传递给被代理的服务器。为了让被代理的服务器可以接收到这两个头部,知道客户端想要切换到WebSocket协议,必须由代理服务器显示地转发。
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
在一个更复杂的例子中,向代理服务器发出的请求中Connection
头字段的值取决于客户端请求报头中是否存在Upgrade
字段:
http {
# 若http_upgrade存在,Connection值为upgrade,升级协议
# 若http_upgrade不存在,Connection值为close,关闭连接
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
默认情况下,如果被代理的服务器在60s内未传输任何数据,连接就会被关闭。这个时间可由proxy_read_timeout
指令修改。或者,可以配置被代理的服务器定期发送 WebSocket ping帧
来重置超时并检查连接是否仍然有效。