我需要做什么才能在 nginx 和 puma 上连接 ActionCable?
What do I need to do to hook up ActionCable on nginx and puma?
我在将 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
这种情况每隔几秒钟就会发生一次。可以在浏览器控制台看到匹配的输出:
首先,我很确定我需要在我的 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 还不错。
更新#2
我还注意到将 config.action_cable.url
更改为 ws://myapp.com
而不是 wss://myapp.com
甚至在重新启动 Rails 后也没有效果。浏览器控制台错误仍然说它正在尝试连接到 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 在评论中帮助我。
我在将 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
这种情况每隔几秒钟就会发生一次。可以在浏览器控制台看到匹配的输出:
首先,我很确定我需要在我的 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 还不错。
更新#2
我还注意到将 config.action_cable.url
更改为 ws://myapp.com
而不是 wss://myapp.com
甚至在重新启动 Rails 后也没有效果。浏览器控制台错误仍然说它正在尝试连接到 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 在评论中帮助我。