web-dev-qa-db-ja.com

ActionCable-本番環境でWebSocketへのアップグレードに失敗しました

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を再起動することを忘れないでください:)それは私にとって問題でした。

17
mityakoval

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";
}
12
Tsutomu

ただし、Rails5やアクションケーブルなどを使用して同じエラーメッセージが表示される場合は、この会話に遅れます&[〜#〜] devise [〜#〜]提案された here のように単純に解決します。これはすべて、セッションを持たないWebソケットサーバーに到達するため、エラーメッセージが表示されます。

app/channels/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

app/config/initializers/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が開発しました

3

このアクションケーブル要求を受け入れるにはNGINX構成の変更が必要

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

上記の行をnginxサイト構成のロケーションブロックに追加し、nginxを再起動します。

1
errakeshpd

私の解決策は、これらの行をproduction.rbファイルに追加することでした:

  config.action_cable.url = 'ws://your_site.com/your_action_cable'
  config.action_cable.allowed_request_origins = [ 'http://your_site.com' ]
0
Aarón Castro

他の投稿は解決策を正しく投稿していますが、他のnginx noobsの問題の場所/修正場所を特定する方法についてもう少し情報を投稿したいと思いました。

Railsエラーにproxy_set_header Upgradeが含まれている場合は、アクションケーブルをマウントしているパスでnginx構成にHTTP_UPGRADE:が必要であることがわかります。(HTTP_UPGRADEに何も渡されないことを意味します) 。問題を修正すると、ログにHTTP_UPGRADE: websocketが表示されます

  • Gotchya 1:オペレーションで言及されているように、変更を加えた後は必ずnginxを再起動してください(私はこれを間違って行っていました)。

  • Gotchya 2:設定が複数のファイルに分割される可能性があるため、nginx設定でincludeステートメントも探します。 location /cable {セクションはserver {の内部にある必要があります。これは、しばらく気づかなかったincludeステートメントとは異なる構成ファイルに含まれていたため、欠落していました。

  • 同様のエラーですが別の問題:あなたのRailsログには、オピニオンが許可されていないことをOPが述べた直前のログに追加のエラーが含まれます。つまり、Rails configを更新する必要があります。

ログはRailsで変更される可能性がありますが、うまくいけば、nginxについて何も知らない人として私が遭遇した問題といくつかの問題を明確にするのに役立ちます。

0
Calvin

で働いた:

location ^~ /cable {
  ...
}

場所には^~が必要です

0

/cableについてnginx設定を変更できます

proxy_set_header X-Forwarded-Proto http;

私はあなたにnginx設定を使用し、myuサーバーにこの変更を追加しました、それはうまくいきます。

0
Alvin