简体   繁体   English

Thin + Nginx + Websockets配置| 轨道

[英]Thin + Nginx + Websockets configurations | Rails

I have a Ruby on Rails 3.2 app with the websocket-rails gem, running in a thin webserver behind a nginx reverse proxy. 我有一个带有websocket-rails gem的Ruby on Rails 3.2应用程序,在nginx反向代理后面的瘦web服务器中运行。

Except for the nginx reverse proxy, everything works just fine. 除了nginx反向代理,一切正常。 By removing the nginx reverse proxy, the websocket communication works just fine. 通过删除nginx反向代理,websocket通信工作正常。 (both development and production). (开发和生产)。 Using nginx as a reverse proxy for the websockets is where the problem starts. 使用nginx作为websockets的反向代理是问题的起点。

Nginx version 1.3.13 and up should be able to support websocket proxying. Nginx 1.3.13及更高版本应该能够支持websocket代理。 Based on the docs here and here I created the following nginx config: 根据这里这里的文档,我创建了以下nginx配置:

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

upstream ravecy {
  server localhost:3000;
  server localhost:3001;
}

server {
  listen 80;
  server_name test.ravecy.com;

  root /var/www/ravecy.com/public;

  location / {
    try_files $uri @ravecy;
  }

  location @ravecy {
    proxy_pass http://ravecy;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_redirect off;
  }
}

Sadly, however, this doesn't work. 然而,遗憾的是,这不起作用。 I don't exactly know why, but it seems to me that nginx isn't handling my websocket connection attempts as websocket connections but regular HTTP connections, as seen from the logs: 我不知道为什么,但在我看来,nginx并没有处理我的websocket连接尝试作为websocket连接而是常规HTTP连接,如日志所示:

==> production.log <==
Started GET "/chat" for 82.170.121.62 at 2013-04-10 12:20:12 +0200
Processing by ApplicationController#chat as HTML
  Rendered application/chat.html.erb within layouts/frontend (0.2ms)
  Rendered layouts/frontend/_navbar.html.erb (6.3ms)
  Rendered layouts/shared/_alert.html.erb (0.0ms)
  Rendered layouts/frontend/_facebook_sdk.html.erb (0.0ms)
Completed 200 OK in 9ms (Views: 8.4ms | ActiveRecord: 0.4ms)
Started GET "/websocket" for 82.170.121.62 at 2013-04-10 12:20:12 +0200

==> websocket_rails.log <==
I [2013-04-10 12:20:12.744] [ConnectionManager] Connection opened: #<Connnection::47398780>

I [2013-04-10 12:20:12.745] [Dispatcher] Started Event: client_connected
I [2013-04-10 12:20:12.745] [Dispatcher] Name: client_connected
I [2013-04-10 12:20:12.745] [Dispatcher] Data: {"connection_id"=>47398780}
I [2013-04-10 12:20:12.745] [Dispatcher] Connection: #<Connnection::47398780>

I [2013-04-10 12:20:12.747] [Dispatcher] Event client_connected Finished in 0.001960819 seconds


==> /var/log/nginx/access.log <==
82.170.121.62 - - [10/Apr/2013:12:20:12 +0200] "GET /chat HTTP/1.1" 200 854 "http://test.ravecy.com/posts" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17"
82.170.121.62 - - [10/Apr/2013:12:20:12 +0200] "GET /assets/frontend-6ad91089203a6026624ce015c2800492.css HTTP/1.1" 304 0 "http://test.ravecy.com/chat" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17"
82.170.121.62 - - [10/Apr/2013:12:20:12 +0200] "GET /assets/frontend-98fa493fc9f482c0d44b31bda5a89135.js HTTP/1.1" 304 0 "http://test.ravecy.com/chat" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17"

==> websocket_rails.log <==
I [2013-04-10 12:20:12.832] [ConnectionManager] Connection closed: #<Connnection::47398780>

I [2013-04-10 12:20:12.832] [Dispatcher] Started Event: client_disconnected
I [2013-04-10 12:20:12.832] [Dispatcher] Name: client_disconnected
I [2013-04-10 12:20:12.832] [Dispatcher] Data: nil
I [2013-04-10 12:20:12.832] [Dispatcher] Connection: #<Connnection::47398780>

I [2013-04-10 12:20:12.833] [Dispatcher] Event client_disconnected Finished in 0.000293462 seconds


==> /var/log/nginx/access.log <==
82.170.121.62 - - [10/Apr/2013:12:20:12 +0200] "GET /websocket HTTP/1.1" 200 398 "-" "-"

Note that the connection is closed within 100ms, even though it should be kept alive. 请注意,连接在100毫秒内关闭,即使它应该保持活动状态。

Further configs: nginx.conf: 进一步的配置:nginx.conf:

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
    worker_connections 768;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    gzip on;
    gzip_disable "msie6";

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

thin config: 瘦配置:

---
chdir: /var/www/ravecy.com
environment: production
address: 127.0.0.1
port: 3000
timeout: 30
log: log/thin.log
pid: tmp/pids/thin.pid
max_conns: 1024
max_persistent_conns: 100
require: []
wait: 30
servers: 2
daemonize: true

nginx version: nginx/1.3.15 url to live example: http://test.ravecy.com/chat nginx版本:nginx / 1.3.15 url实时示例: http//test.ravecy.com/chat

Also note: upon executing new WebSocket("ws://test.ravecy.com/websocket") in the JS console, the browser prompts "Unexpected response code: 200". 另请注意:在JS控制台中执行new WebSocket("ws://test.ravecy.com/websocket")时,浏览器会提示“意外的响应代码:200”。

I'm pretty desperate to make this work and no longer know what I should do. 我非常渴望完成这项工作,不再知道应该做些什么。

Telnet results NGINX: Telnet结果NGINX:

GET /websocket HTTP/1.1
Host: test.ravecy.com
Connection: Upgrade
Upgrade: WebSocket

HTTP/1.1 200 OK
Server: nginx/1.3.15
Date: Sat, 13 Apr 2013 19:50:35 GMT
Content-Type: text/json
Transfer-Encoding: chunked
Connection: keep-alive

152
[["client_connected",{"id":null,"channel":null,"data":{"connection_id":37160040},"success":null,"result":null,"server_token":null}]][["users",{"id":null,"channel":null,"data":[],"success":null,"result":null,"server_token":null}]][["client_connected",{"id":null,"channel":null,"data":{},"success":false,"result":null,"server_token":null}]]

Telnet results direct to thin: Telnet结果直接导致瘦:

GET /websocket HTTP/1.1
Host: test.ravecy.com
Connection: Upgrade
Upgrade: WebSocket

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: 
WebSocket-Location: ws://test.ravecy.com/websocket

[["client_connected",{"id":null,"channel":null,"data":{"connection_id":37489460},"success":null,"result":null,"server_token":null}]][["users",{"id":null,"channel":null,"data":[],"success":null,"result":null,"server_token":null}]][["client_connected",{"id":null,"channel":null,"data":{},"success":false,"result":null,"server_token":null}]]

Obviously, this is were stuff goes wrong. 显然,这是出了问题。 But why? 但为什么?

Based on the telnet results I noted that I used "Upgrade" with a capital "U". 基于telnet结果,我注意到我使用了“升级”,大写字母为“U”。 Using "Upgrade" instead of "upgrade" fixed all of the problems I had... 使用“升级”代替“升级”修复了我遇到的所有问题......

Yeah. 是啊。 The connection upgrade syntax for http to ws at times is case-sensitive http到ws的连接升级语法有时区分大小写

So complete server config looks like this: 所以完整的服务器配置如下所示:

server {
listen 80;
server_name server.com;

root /var/www/my-app/current/public;

try_files $uri/index.html $uri @app;

location @app {
    proxy_pass http://app;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
}

# enables WS support
location /websocket {
    proxy_pass http://app;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}

error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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