Nginx 反向代理 WebSocket 超时

标签 nginx websocket nginx-reverse-proxy

我正在使用 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 day ,所以只剩下后端。

    直接测试后端

    我的第一个建议是您尝试直接连接到后端并确认问题仍然存在(出于故障排除的目的,将 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 proxying doc 中有一条注释。这暗示了一个很好的解决方案:

    Alternatively, the proxied server can be configured to periodically send WebSocket ping frames to reset the timeout and check if the connection is still alive.



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

    关于Nginx 反向代理 WebSocket 超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52078122/

    相关文章:

    php - Laravel Socialite - 谷歌登录失败 "Missing required parameter: client_id"虽然指定

    nginx - 在 GKE 上使用 nginx 入口 Controller 时负载均衡器的节点不健康

    docker - 单个IP和端口上有多个DockerContainers WebUI

    c# - 为什么内部项目使用 ASP.Net Web Api 而不是 SignalR

    上游解析为 IPv6 时 Nginx 连接失败

    Nginx 有条件地重写 uri

    node.js - A 服务器的套接字连接问题(ExpressJS + Nodejs + Nginx + SSL)

    redirect - 子域的 Nginx 变量?

    node.js - Bitfinex 的 Websocket API "hello world"导致 ECONNREFUSED 错误

    python - Websocket/event-source/... 实现将双向 RPC 暴露给 python/django 应用程序