nginx - 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
不必要)而关闭,无论它打开多长时间或涉及多少中间框。
推荐阅读
- sql-server - 选择特定的存在但仍包含不需要的结果
- c# - 使用循环概念从字符串中拆分运算符
- google-apps-script - 谷歌电子表格脚本 - 将值移动到特定单元格
- bash - 在 shell 脚本中使用“睡眠”功能时出现问题
- azure - “云端点创建失败”的一些问题
- python - ValueError:在系统中找不到外部 ID:todo_report.report_todo_task_template
- reactjs - 我们可以将sectionList(或滚动视图)的粘性标题粘贴到滚动视图顶部的相对位置吗?
- hyperledger-fabric - 超级账本的 fabcar.go 链码不接受更改和修改,始终运行以前的链码
- c# - 如何包含正确小数点的货币?
- sql-server - 在嵌套路径中返回多个值的 XML 查询