带有nginx和puma的WebSockets(websocket-rails)

时间:2014-10-01 14:47:23

标签: ruby-on-rails nginx websocket puma

使用websocket-rails gem,我能够在开发中直接通过puma成功获得websocket连接,但是,当部署到生产并尝试通过nginx访问websocket时(传递给puma)我有几个错误:一个在nginx错误日志中:

[info] 14340#0: *7 upstream timed out (110: Connection 
timed out) while proxying upgraded connection, client: 123.45.67.89, server: 
foo.com, request: "GET /websocket HTTP/1.1", upstream: 
"http://unix:///opt/oneconnect/shared/tmp/sockets/puma.sock:/websocket", host: 
"foo.com"

...和javascript控制台上的一个:

WebSocket connection to 'ws://foo.com/websocket' failed: Error during WebSocket handshake: Unexpected response code: 301 

我发现nginx(我使用的版本是1.4.6)能够使用websocket而requires special configuration,我已经尝试过(获得上述错误)。这是我的nginx.conf:

upstream oneconnect {
        server unix:///opt/oneconnect/shared/tmp/sockets/puma.sock;
}

server {
        listen 80;
        listen 443 ssl;

        #ssl on;
        ssl_certificate         /etc/ssl/foo.com.crt;
        ssl_certificate_key     /etc/ssl/foo.com.key;

        root /opt/oneconnect/current/public;
        try_files $uri @oneconnect;

        access_log /opt/oneconnect/current/log/nginx.access.log;
        error_log /opt/oneconnect/current/log/nginx.error.log info;

        server_name foo.com;

        location ~ ^/(assets)/  {
          root /opt/oneconnect/current/public;
          gzip_static on;
          expires max;
          add_header Cache-Control public;
        }

        location /websocket/ {
            proxy_pass http://oneconnect;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        location @oneconnect {
            proxy_read_timeout 300;
            proxy_connect_timeout 300;
            proxy_redirect off;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://oneconnect;
        }
}

我假设我错过了一些简单的东西,但我在这一点上难过并且用Google搜索直到我的眼睛开始流血。如果有人可以帮助它将非常感激,或者只是指出如何调试这些连接(似乎很难从ws连接获得调试信息)。谢谢你的时间。

1 个答案:

答案 0 :(得分:1)

假设你已经有了eventmachine的初始化程序

config/initializers/eventmachine.rb
Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive?

nginx site conf:

upstream puma_project_production {
  server unix:/var/www/project/shared/tmp/sockets/puma.sock fail_timeout=0;
}

server {
  listen 80;

  client_max_body_size 4G;
  keepalive_timeout 10;

  error_page 500 502 504 /500.html;
  error_page 503 @503;

  server_name localhost project.local;
  root /var/www/project/current/public;
  try_files $uri/index.html $uri @puma_project_production;

  location @puma_project_production {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://puma_project_production;
    # limit_req zone=one;
    access_log /var/www/project/shared/log/nginx.access.log;
    error_log /var/www/project/shared/log/nginx.error.log;
  }

  location ^~ /assets/ {

    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  location = /50x.html {
    root html;
  }

  location = /404.html {
    root html;
  }

  location @503 {
    error_page 405 = /system/maintenance.html;
    if (-f $document_root/system/maintenance.html) {
      rewrite ^(.*)$ /system/maintenance.html break;
    }
    rewrite ^(.*)$ /503.html break;
  }

  if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
    return 405;
  }

  if (-f $document_root/system/maintenance.html) {
    return 503;
  }
location /websocket {
  proxy_pass http://puma_project_production;
           proxy_redirect off;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
  location ~ \.(php|rb)$ {
    return 405;
  }
}