简体   繁体   中英

WebSockets with nginx and puma (websocket-rails)

Using the websocket-rails gem, I'm able to successfully get a websocket connection straight through puma in development, however, when deployed to production and attempting to access the websocket through nginx (passing off to puma) I have a couple of errors: one in the nginx error log:

[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"

... and one on the javascript console:

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

I found that nginx (the version I'm using is 1.4.6) is capable of websocket use but requires special configuration , which I've already attemped (getting the errors above). Here's my 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;
        }
}

I'm assuming that I'm missing something simple, but I'm stumped at this point and have Googled until my eyes started bleeding. If anyone could help it would be much appreciated, or maybe just point me to how to debug these connections (it seems hard to get debug info from a ws connection). Thanks for your time.

Assuming u have already initializer for 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;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM