35

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

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

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

诚然,我对 nginx 配置并不是那么精通,那么,甚至可以将 nginx 配置为 websocket 服务器的反向代理吗?还是我必须等待 nginx 为新的 websocket 握手提供支持?假设要求应用程序服务器和 websocket 服务器都在端口 80 上侦听,这是否意味着我现在必须在没有 nginx 的单独服务器上运行 Thin?

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

-约翰

4

7 回答 7

26

您目前不能为此使用 nginx [这不再是真的],但我建议您查看 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
于 2010-04-08T14:51:22.923 回答
12

如何使用我的nginx_tcp_proxy_module 模块

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

于 2010-09-14T09:03:05.463 回答
11

nginx (>= 1.3.13) 现在支持反向代理 websocket。

# 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;
    }
}
于 2013-02-20T10:00:38.083 回答
7

开箱即用(即官方来源)Nginx 只能与上游(=后端)建立 HTTP 1.0 连接,这意味着不可能保持连接:Nginx 将选择一个上游服务器,打开到它的连接,代理,缓存(如果你想要) 并关闭连接。而已。

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

编辑:Nginx 从 1.1.4 版本开始支持 HTTP 1.1 到后端和 keepalive。支持“fastcgi”和“代理”上游。这是文档

于 2010-03-10T19:48:11.850 回答
5

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

于 2012-05-15T06:23:51.640 回答
3

Nginx 与新的 HTTP 推送模块怎么样:http: //pushmodule.slact.net/。它负责处理反向代理可能不得不担心的连接杂耍(可以这么说)。对于尚未完全混合的 Websocket,它无疑是一个可行的替代方案。我知道 HTTP Push 模块的开发人员仍在开发一个完全稳定的版本,但它正在积极开发中。在生产代码库中使用了它的多个版本。引用作者的话,“一个有用的工具,名字很无聊。”

于 2010-03-10T20:08:01.617 回答
2

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

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

于 2010-05-26T11:51:55.803 回答