我需要做什么才能在 nginx 和 puma 上连接 ActionCable?

问题描述

我无法将 ActionCable 连接到我的生产环境中,并且相关问题没有有效的解决方案。我在 Ubuntu 20.04 上使用 Rails 6.1.3.2 的 Nginx+puma 设置。我已经确认 redis-server 正在端口 6379 上运行,并且 Rails 正在作为生产运行。

这是我在日志中得到的内容

I,[2021-05-25T22:47:25.335711 #72559]  INFO -- : [5d1a85f7-0102-4d25-bd4e-d81355b846ee] Started GET "/cable" for 74.111.15.223 at 2021-05-25 22:47:25 +0000
I,[2021-05-25T22:47:25.336283 #72559]  INFO -- : [5d1a85f7-0102-4d25-bd4e-d81355b846ee] Started GET "/cable/"[non-WebSocket] for 74.111.15.223 at 2021-05-25 22:47:25 +0000
E,[2021-05-25T22:47:25.336344 #72559] ERROR -- : [5d1a85f7-0102-4d25-bd4e-d81355b846ee] Failed to upgrade to WebSocket (REQUEST_METHOD: GET,HTTP_CONNECTION: close,HTTP_UPGRADE: )
I,[2021-05-25T22:47:25.336377 #72559]  INFO -- : [5d1a85f7-0102-4d25-bd4e-d81355b846ee] Finished "/cable/"[non-WebSocket] for 74.111.15.223 at 2021-05-25 22:47:25 +0000

这种情况每隔几秒就会发生一次。您可以在浏览器控制台中看到匹配的输出

enter image description here

首先,我很确定我需要在我的 Nginx 站点配置中添加一些部分,例如 /cable 部分,但我还没有想出正确的设置。这是我当前的配置:

server {
    root /home/rails/myapp/current/public;
    server_name myapp.com;
    index index.htm index.html;

        location ~ /.well-kNown {
                allow all;
        }

        location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # needed to allow serving of assets and other public files
    location ~ ^/(assets|packs|graphs)/ {
        gzip_static on;
        expires 1y;
        add_header Cache-Control public;
        add_header Last-Modified "";
        add_header ETag "";
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-Nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = myapp.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen   80;
    server_name myapp.com;
    return 404; # managed by Certbot
}

这是我的config/cable.yml

development:
  adapter: async

test:
  adapter: test

production:
  adapter: redis
  url: <%= ENV.fetch("REdis_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: myapp_production

config/environments/production.rb 中,我将这些行注释掉了:

  # Mount Action Cable outside main process or domain.
  # config.action_cable.mount_path = nil
  # config.action_cable.url = 'wss://example.com/cable'
  # config.action_cable.allowed_request_origins = [ 'http://example.com',/http:\/\/example.*/ ]

我没有在我的路线或任何东西中手动安装 ActionCable。这是您可以获得的设置标准。我认为答案集中在正确的 Nginx 配置中,但我不知道它应该是什么。不过,也许还需要 Rails 配置设置。我不记得在与乘客一起部署时必须改变任何东西,但也许 puma 是一个不同的故事。

更新

我还注意到其他问题 like this one 中的许多建议解决方案似乎引用了 .sock 中的 tmp/sockets/ 文件。不过,我的 sockets/ 目录是空的。除了 ActionCable 之外,Web 服务器运行良好。

更新 #2

我还注意到,即使在重新启动 Rails 后,将 config.action_cable.url 更改为类似 ws://myapp.com 而不是 wss://myapp.com 也没有任何效果。浏览器控制台错误仍然说它正在尝试连接到 wss://myapp.com。可能是由于我如何设置强制将 HTTP 重定向到 HTTPS。不知道跟这个有关系吗?

解决方法

我成功了。以下是我需要的设置:

nginx 配置

必须修改我问题中配置的 server 部分,以包含 //cable 位置的以下两个部分:

        location / {
                proxy_pass http://localhost:3000;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
        }

        location /cable {
                proxy_pass http://localhost:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade "websocket";
                proxy_set_header Connection "Upgrade";
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

config/environments/production.rb

  # Change myapp.com to your app's location
  config.action_cable.allowed_request_origins = [ 'https://myapp.com' ]
  config.hosts << "myapp.com"
  config.hosts << "localhost"

非常感谢 Lam Phan 在评论中帮助我。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...