nginx可以用作后端websocket服务器的反向代理吗?

时间:2010-03-10 18:07:32

标签: ruby-on-rails nginx reverse-proxy websocket thin

我们正在开发一个需要利用html5 websockets的Ruby on Rails应用程序。目前,我们有两个独立的“服务器”可以说:我们的主应用程序在nginx +乘客上运行,另一个服务器使用Pratik Naik的Cramp框架(在Thin上运行)来处理websocket连接。

理想情况下,当需要部署时,我们会在nginx + passenger上运行rails应用程序,而websocket服务器将在nginx后面代理,因此我们不需要在不同的情况下运行websocket服务器端口。

问题是,在这种设置中,似乎nginx过早地关闭了与Thin的连接。已成功建立与瘦服务器的连接,然后立即关闭200响应代码。我们的猜测是nginx没有意识到客户端正在尝试为websocket流量建立一个长期运行的连接。

不可否认,我对nginx配置并不是那么精明,所以,甚至可以配置nginx作为websocket服务器的反向代理吗?或者我是否必须等待nginx为新的websocket握手提供支持?假设让app服务器和websocket服务器都在端口80上监听是一个要求,那么这可能意味着我必须在没有nginx的单独服务器上运行Thin吗?

提前感谢任何建议或意见。 :)

-John

7 个答案:

答案 0 :(得分:26)

你不能将nginx用于当前的 [it's not true anymore] ,但我建议你看一下HAProxy。我已将它用于此目的。

诀窍是设置长时间超时,以便不关闭套接字连接。类似的东西:

timeout client  86400000 # In the frontend
timeout server  86400000 # In the backend

如果您想在同一端口上提供rails和cramp应用程序,您可以使用ACL规则来检测websocket连接并使用不同的后端。所以你的haproxy前端配置看起来像

frontend all 0.0.0.0:80
  timeout client    86400000
  default_backend   rails_backend
  acl websocket hdr(Upgrade)    -i WebSocket
  use_backend   cramp_backend   if websocket

为了完整性,后端看起来像

backend cramp_backend
  timeout server  86400000
  server cramp1 localhost:8090 maxconn 200 check

答案 1 :(得分:12)

如何使用我的nginx_tcp_proxy_module module

此模块专为使用Nginx的常规TCP代理而设计。我认为它也适用于websocket。我只是在开发分支中添加tcp_ssl_module。

答案 2 :(得分:11)

nginx (>= 1.3.13) now supports反向代理websockets。

# the upstream server doesn't need a prefix! 
# no need for wss:// or http:// because nginx will upgrade to http1.1 in the config below
upstream app_server {
    server localhost:3000;
}

server {
    # ...

    location / {
        proxy_pass http://app_server;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header 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;
    }
}

答案 3 :(得分:7)

开箱即用(即官方消息来源)Nginx只能建立到上游(=后端)的HTTP 1.0连接,这意味着没有任何keepalive可能:Nginx将选择一个上游服务器,打开它的连接,代理,缓存(如果你想)并关闭连接。就是这样。

这是需要持久连接到后端的框架无法通过Nginx工作的根本原因(没有HTTP / 1.1 =没有keepalive,我猜没有websockets)。尽管有这个缺点,但有一个明显的好处:Nginx可以选择退出多个上游(负载平衡)并将故障转移到活动状态,以防其中一些失败。

编辑:Nginx支持HTTP 1.1到后端&自版本1.1.4以来的keepalive。支持“fastcgi”和“代理”上游。 Here it is the docs

答案 4 :(得分:5)

对于任何想知道同样问题的人,nginx现在正式支持HTTP 1.1上游。有关“keepalive”和“proxy_http_version 1.1”的信息,请参阅nginx文档。

答案 5 :(得分:3)

Nginx如何使用新的HTTP Push模块:http://pushmodule.slact.net/。它负责处理(可以这么说)人们可能不得不担心反向代理。它当然是Websockets的可行替代品,但尚未完全融入其中。我知道HTTP Push模块的开发人员仍在开发一个完全稳定的版本,但它正在积极开发中。它的版本在生产代码库中使用。引用作者,“一个有点无聊名称的有用工具。”

答案 6 :(得分:2)

我使用nginx将代理转换为具有长轮询连接的彗星式服务器,并且效果很好。确保将proxy_send_timeout和proxy_read_timeout配置为适当的值。还要确保nginx代理的后端服务器支持http 1.0,因为我认为nginx的代理模块还没有http 1.1。

只是为了澄清一些答案中的一些混淆:Keepalive允许客户端重用连接来发送另一个HTTP请求。它与长轮询或保持连接打开没有任何关系,直到事件发生,这是原始问题所询问的。因此,与nginx的代理模块仅支持没有keepalive的HTTP 1.0无关。