簡體   English   中英

ActionCable - 無法在生產中升級到 WebSocket

[英]ActionCable - Failed to upgrade to WebSocket in production

ActionCable 在生產中不起作用。 在開發中運行良好,但在生產中運行不佳。

在 Ubuntu 14.04 上使用 Puma 運行 Nginx。 我已經檢查過 redis-server 是否已啟動並正在運行。

Rails -v 5.0.0.1

production.log

INFO -- : Started GET "/cable/"[non-WebSocket] for 178.213.184.193 at 2016-11-25 14:55:39 +0100
ERROR -- : Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: close, HTTP_UPGRADE: )
INFO -- : Finished "/cable/"[non-WebSocket] for 178.213.184.193 at 2016-11-25 14:55:39 +0100

來自客戶的請求:

GET ws://mityakoval.com/cable HTTP/1.1
Host: mityakoval.com
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://mityakoval.com
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,uk;q=0.2,nb;q=0.2
Cookie: _vaktdagboka_session=******
Sec-WebSocket-Key: *******
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: actioncable-v1-json, actioncable-unsupported

回應:

HTTP/1.1 404 Not Found
Server: nginx/1.4.6 (Ubuntu)
Date: Fri, 25 Nov 2016 13:52:21 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: no-cache
X-Request-Id: d6374238-69ef-476e-8fc5-e2f8bbb663de
X-Runtime: 0.002500

nginx.conf

upstream puma {
  server unix:///home/mityakoval/apps/vaktdagboka/shared/tmp/sockets/vaktdagboka-puma.sock;
}

server {
  listen 80 default_server deferred;
  # server_name example.com;

  root /home/mityakoval/apps/vaktdagboka/current/public;
  access_log /home/mityakoval/apps/vaktdagboka/current/log/nginx.access.log;
  error_log /home/mityakoval/apps/vaktdagboka/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    proxy_pass http://puma;
  }

  location /cable {
    proxy_pass http://puma;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
  }

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

cable.yml :

redis: &redis
  adapter: redis
  url: redis://127.0.0.1:6379

production: *redis

development:
  adapter: async

test:
  adapter: async

production.rb

config.action_cable.allowed_request_origins = ["http://mityakoval.com"]

routes.rb

mount ActionCable.server, at: '/cable'

更新:

不要忘記重新啟動 nginx :) 那是我的問題。

您應該將proxy_pass屬性的值從http://puma更改為http://puma/cable

因此, /cable的正確location部分將是:

location /cable {
  proxy_pass http://puma/cable;
  proxy_http_version 1.1;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "Upgrade";
}

雖然其他帖子已經正確發布了解決方案,但我想我會發布更多關於如何確定問題所在/為其他 nginx 新手修復問題的信息。

如果 rails 錯誤包含HTTP_UPGRADE:您就會知道您的 nginx 配置需要在您安裝操作電纜的路徑上proxy_set_header Upgrade (意味着沒有傳遞給 HTTP_UPGRADE)。 解決問題后,我的日志顯示HTTP_UPGRADE: websocket

  • Gotchya 1:如操作所述,請確保在進行更改后重新啟動 nginx(我這樣做是錯誤的)。

  • Gotchya 2:還要在 nginx 配置中查找包含語句,因為您的配置可能會拆分到多個文件中。 location /cable {部分應該在server {內部,在我的情況下它丟失了,因為它與我暫時沒有注意到的包含語句位於不同的配置文件中。

  • 類似的錯誤但不同的問題:您的 rails 日志將在日志中包含一個額外的錯誤,就在 OP 提到的那個說不允許原點之前,即當您的 rails 配置需要更新時,另一個答案提到更新 config.action_cable。 allowed_request_origins。

日志記錄可能會隨着 Rails 發生變化,但希望這有助於澄清問題所在以及我作為一個對 nginx 一無所知的人遇到的一些問題。

但是,對於使用 Rails5、Action Cable 等遇到相同錯誤消息的任何人來說,這次談話已經很晚了。 DEVISE您只需按照此處的建議解決它。 這一切都歸結為 Web 套接字服務器沒有會話,因此出現錯誤消息。

應用程序/頻道/application_cable/connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.name
    end

    protected
      def find_verified_user
        verified_user = User.find_by(id: cookies.signed['user.id'])
        if verified_user && cookies.signed['user.expires_at'] > Time.now
          verified_user
        else
          reject_unauthorized_connection
        end
      end
  end
end

應用程序/配置/初始化程序/warden_hooks.rb

Warden::Manager.after_set_user do |user,auth,opts|
  scope = opts[:scope]
  auth.cookies.signed["#{scope}.id"] = user.id
  auth.cookies.signed["#{scope}.expires_at"] = 30.minutes.from_now
end
Warden::Manager.before_logout do |user, auth, opts|
  scope = opts[:scope]
  auth.cookies.signed["#{scope}.id"] = nil
  auth.cookies.signed["#{scope}.expires_at"] = nil
end

解決方案由 Greg Molnar 開發

需要 NGINX 配置的分辨率更改為接受此操作電纜請求

location / {
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

將上述行添加到 nginx 站點配置中的位置塊,然后重新啟動 nginx。

您可以更改有關/cable nginx 配置

proxy_set_header X-Forwarded-Proto http;

我使用了你的 nginx 配置並在 myu 服務器上添加了這個更改,它工作正常。

我的解決方案是將這些行添加到我的production.rb文件中:

  config.action_cable.url = 'ws://your_site.com/your_action_cable'
  config.action_cable.allowed_request_origins = [ 'http://your_site.com' ]

曾與:

location ^~ /cable {
  ...
}

位置需要^~

您的 cable.yml 文件應如下所示:

production:
    adapter: redis
    url: <%=ENV['REDIS_URL']%>

然后你應該在環境中設置這個密鑰,應該是這樣的:

REDIS_URL: 'redis://redistogo:keyblahblahblhblah'

此外,您應該在 production.rb 中包含此內容:

config.web_socket_server_url = "wss://YOUR_URL.com/cable"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM