You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 5.2 ActionCable配置SSL后生产环境无法工作求助

解决AWS负载均衡SSL下ActionCable WebSocket连接失败的问题

从你的日志能直接定位到核心问题:HTTP_UPGRADE: 是空值,这说明客户端发送的WebSocket协议升级请求头没有被正确传递到Rails应用层,导致ActionCable无法完成WebSocket握手。结合你的架构(AWS ALB + Nginx + Unicorn + Rails 5.2),咱们一步步来修复:

1. 先把AWS负载均衡(ALB)的WebSocket支持配置好

AWS ALB默认支持WebSocket,但得确保这几点没遗漏:

  • 你的HTTPS监听必须用HTTP/1.1协议(WebSocket完全依赖HTTP/1.1的Upgrade机制)
  • 目标组要开启WebSocket保持连接,同时把超时时间设长些(建议至少30秒以上,适配WebSocket的持久连接特性)
  • 检查ALB的转发规则,确保/cable路径的请求能正确转发到后端Nginx,而且没有修改或丢弃Upgrade和Connection这两个关键请求头

2. 调整Nginx配置,精准处理WebSocket请求

原来的配置里WebSocket相关头是放在@unicorn块里的,但可能没精准匹配/cable路径。建议单独给/cable加一个location配置,确保协议升级的头能准确传递:

upstream unicorn {
  server unix:/usr/share/nginx/html/demo_app/shared/tmp/unicorn.demo_app.sock fail_timeout=0;
}

server {
  listen 80;
  server_name example.com;
  root /usr/share/nginx/html/demo_app/current/public;

  try_files $uri/index.html $uri @unicorn;

  # 专门处理ActionCable的WebSocket请求
  location /cable {
    proxy_pass http://unicorn;
    proxy_http_version 1.1;
    # 核心:传递WebSocket升级必需的头
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    # 传递客户端真实IP和协议信息
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_redirect off;
    # 设置长连接超时,适配WebSocket持久连接
    proxy_connect_timeout 7d;
    proxy_send_timeout 7d;
    proxy_read_timeout 7d;
  }

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://unicorn;
    proxy_set_header X-Real-IP $remote_addr;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

3. 完善Rails production.rb配置

除了你已有的配置,建议添加请求来源限制,同时确保ActionCable的核心配置正确:

# config/environments/production.rb
config.action_cable.url = ENV["SOCKET_URL"] # 确认这个环境变量值是wss://example.com/cable
config.action_cable.allowed_request_origins = [/https:\/\/example\.com/] # 只允许当前域名发起WebSocket请求
config.action_cable.disable_request_forgery_protection = true # 如果暂时关闭了CSRF保护,后续前端能正确传递CSRF token后建议开启

4. 验证修复效果

修改完配置后,依次重启Nginx和Unicorn:

sudo service nginx restart
# 重启Unicorn(根据你的部署方式调整,比如用Capistrano的话就是cap production unicorn:restart)

之后查看Rails日志,如果看到类似下面的内容,就说明WebSocket连接成功了:

Started GET "/cable" for xxx.xxx.xxx.xxx at xxxx-xx-xx xx:xx:xx +0000
Started GET "/cable/" [WebSocket] for xxx.xxx.xxx.xxx at xxxx-xx-xx xx:xx:xx +0000
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: upgrade, HTTP_UPGRADE: websocket)

内容的提问来源于stack exchange,提问作者Prashant Vardhan Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:27:58