nginx 反向代理 WebSocket 超时



我正在使用java-websocket来满足我的websocket需求,在一个wowza应用程序中,并使用nginx进行SSL,将请求代理到java。

问题是连接似乎在服务器端恰好 1 小时后被切断。客户端甚至不知道它已断开连接了很长一段时间。我不想只是调整nginx上的超时,我想了解为什么连接被终止,因为套接字照常运行,直到它不正常。

编辑: 忘记发布配置:

location /websocket/ {
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
include conf.d/proxy_websocket;
proxy_connect_timeout 1d;
proxy_send_timeout 1d;
proxy_read_timeout 1d;
}

其中包括配置:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass                      http://127.0.0.1:1938/;
  • Nginx/1.12.2
  • CentOS Linux 发行版 7.5.1804 (核心版(
  • Java WebSocket 1.3.8 (GitHub(

超时可能来自客户端、nginx 或后端。当你说它被切断"服务器端"时,我认为这意味着你已经证明它不是客户端。您的nginx配置看起来不应该超时1天,因此只剩下后端。

直接测试后端

我的第一个建议是尝试直接连接到后端并确认问题仍然存在(出于故障排除目的,将nginx从图片中删除(。请注意,如果使用浏览器不切实际,您可以使用命令行实用程序(如curl(执行此操作。下面是一个示例测试命令:

time curl --trace-ascii curl-dump.txt -i -N 
-H "Host: example.com" 
-H "Connection: Upgrade" 
-H "Upgrade: websocket" 
-H "Sec-WebSocket-Version: 13" 
-H "Sec-WebSocket-Key: BOGUS+KEY+HERE+IS+FINE==" 
http://127.0.0.1:8080

在我的(工作(案例中,运行上述示例无限期保持打开状态(我手动使用 Ctrl-C 停止(,因为 curl 和我的服务器都没有实现超时。但是,当我将其更改为通过nginx作为代理(默认超时为1分钟(时,如下所示,我在几乎正好1分钟后看到了nginx的504响应。

time curl -i -N --insecure 
-H "Host: example.com" 
https://127.0.0.1:443/proxied-path
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.14.2
Date: Thu, 19 Sep 2019 21:37:47 GMT
Content-Type: text/html
Content-Length: 183
Connection: keep-alive
<html>
<head><title>504 Gateway Time-out</title></head>
<body bgcolor="white">
<center><h1>504 Gateway Time-out</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>
real    1m0.207s
user    0m0.048s
sys 0m0.042s

其他想法

有人提到尝试proxy_ignore_client_abort但除非客户端关闭连接,否则这应该没有任何区别。此外,尽管这可能会保持内部连接打开,但我认为它无法保持端到端流的完整。

你可能想尝试proxy_socket_keepalive,尽管这需要nginx>= 1.15.6。

最后,WebSocket 代理文档中有一个注释,提示了一个好的解决方案:

或者,可以将代理服务器配置为定期发送 WebSocket ping 帧以重置超时并检查连接是否仍处于活动状态。

如果您可以控制后端并希望连接无限期地保持打开状态,则定期向客户端发送"ping"帧(假设使用了Web浏览器,则客户端不需要更改,因为它是作为规范的一部分实现的(应该可以防止连接由于不活动而关闭(使proxy_read_timeout不必要的(,无论它打开多长时间或涉及多少个中间盒。

很可能是因为您对 websocket 代理的配置需要稍微调整,但既然您问:

反向代理服务器面临一些挑战 支持 WebSocket。一是WebSocket是一个逐跳协议, 因此,当代理服务器拦截来自客户端的升级请求时,它 需要向后端服务器发送自己的升级请求,包括 相应的标头。另外,由于WebSocket连接很长 lived,而不是 HTTP 使用的典型短寿命连接, 反向代理需要允许这些连接保持打开状态, 而不是因为它们似乎闲置而关闭它们。

在处理 websocket 代理的位置指令中,您需要包含标头,这是 Nginx 给出的示例:

location /wsapp/ {
proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}

这现在应该有效,因为:

NGINX通过允许在 客户端和后端服务器。供 NGINX 发送升级请求 从客户端到后端服务器,升级和连接 必须显式设置标头,如本例所示

我还建议您查看Nginx Nchan模块,该模块将websocket功能直接添加到Nginx中。效果很好。

最新更新