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

3
我在我的生产环境中遇到了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配置设置也是必需的,但我不记得在使用passenger部署时需要更改任何设置,但也许puma是另一回事。
更新:我还注意到,在其他问题的提议解决方案中,像这样的,似乎引用了tmp/sockets/中的.sock文件。但是我的sockets/目录是空的。Web服务器除了ActionCable之外运行良好。
第二次更新
我还注意到,即使在重新启动Rails之后,将config.action_cable.url更改为ws://myapp.com而不是wss://myapp.com也没有任何效果。浏览器控制台错误仍然显示它正在尝试连接到wss://myapp.com。可能是因为我设置了强制重定向HTTP到HTTPS的方式造成的。我想知道这是否有任何关系?

我看到它返回了404错误,所以原因可能与配置config.action_cable.allowed_request_originsconfig.action_cable.allow_same_origin_as_host有关。 - undefined
@LamPhan 我本以为可能是这样,但是将它们分别设置为我的应用程序URL和true后,似乎没有任何效果,即使重新启动了Rails和nginx。 - undefined
我觉得你漏掉了 location /cable { ... },你可以尝试使用我的生产配置:location /cable { proxy_pass http://backend; 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; } location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }在你的情况下,将 http://backend 替换为 http://localhost:3000 - undefined
@LamPhan 我添加了那个配置,并且nginx成功重启了。但是问题没有解决。在浏览器中访问/cable告诉我要在我的Rails生产配置中添加config.hosts << "localhost",我已经添加了。现在访问页面显示"页面未找到"。对/cable的请求仍然返回404错误。有可能我需要手动启动ActionCable在那个位置吗? - undefined
在我的生产配置中,我设置了upstream backend并将代理location \cable指向它,但是我在你的配置中没有看到这个。你可以在这里检查:https://dev59.com/ZrPma4cB1Zd3GeqPn0fI - undefined
1个回答

5

我搞定了。以下是我需要的设置:

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帮助我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接