Nginx 在建立 ActionCable 连接后立即丢弃它们
Posted
技术标签:
【中文标题】Nginx 在建立 ActionCable 连接后立即丢弃它们【英文标题】:Nginx drops ActionCable connections immediately after they're established 【发布时间】:2020-05-21 13:55:33 【问题描述】:使用 puma 和在 nginx 后面运行的 Rails 6。 nginx 配置如下所示:
upstream APPNAME
server unix:/tmp/APPNAME.sock fail_timeout=0;
server
listen 443 ssl;
# ... server_name, ssl_certificate, etc.
location /cable
proxy_pass http://APPNAME;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
location @APPNAME
proxy_pass http://APPNAME;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
当ActionCable 连接来自浏览器时,它能够订阅频道并接收响应。但它永远不会收到任何“ping”消息,并且会继续重新连接(在我的情况下每 10 秒一次)。
使用curl
直接测试连接,当直接在服务器上运行puma时它可以正常工作(在本地主机端口上,因为配置使用Unix套接字)。
time curl --trace-ascii curl-dump.txt -i -k -N \
-H "Host: <REPLACE_WITH_HOSTNAME>" \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: BOGUS+KEY+HERE+IS+FINE==" \
http://localhost:3000/cable
但是当连接 URL 改为指向 nginx 端口号时,结果类似于浏览器:它永远不会收到任何“ping”消息。
【问题讨论】:
【参考方案1】:我曾假设location @APPNAME
部分中的配置将用于调用proxy_pass
的其他位置,但回想起来我发现它根本不是,这就是必须重复proxy_set_header
指令的原因。
所以location /cable
部分需要包含使location @APPNAME
正常工作的所有 指令。我发现添加proxy_redirect off;
解决了这个问题。
所以下面的位置配置解决了这个问题:
location /cable
proxy_pass http://APPNAME;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
【讨论】:
以上是关于Nginx 在建立 ActionCable 连接后立即丢弃它们的主要内容,如果未能解决你的问题,请参考以下文章
Rails5 + ActionCable:与'ws:// {hostname} / cable'的WebSocket连接失败:WebSocket在建立连接之前关闭
如何在生产中使用 Nginx 和 Unicorn 配置 ActionCable?
无法连接到 Elastic Beanstalk 上的 ActionCable