Rails 5.2 ActionCable配置SSL后生产环境无法工作求助
从你的日志能直接定位到核心问题: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

