使用HAProxy负载平衡与Tornado应用程序的WebSocket连接?

时间:2012-06-05 11:06:33

标签: proxy nginx websocket tornado haproxy

我正在使用一个使用websocket处理程序的Tornado应用程序。我正在使用Supervisord运行应用程序的多个实例,但是我无法平衡websocket连接。

我知道nginx不支持处理开箱即用的websockets,但我按照http://www.letseehere.com/reverse-proxy-web-sockets中的说明使用nginx tcp_proxy模块来反转代理websocket连接。但是,这不起作用,因为模块无法路由websocket url(例如:ws:// localhost:80 / something)。所以它不适用于我在Tornado应用程序中定义的URL路由。

从我对网络的研究来看,似乎HAProxy是对我的websocket连接进行负载均衡的方法。但是,我很难找到任何体面的指导来设置HAProxy来加载平衡websocket连接,并且还能够处理websocket URL路由。

我真的很感激有关如何实现这一目标的一些详细指示。我也完全接受其他解决方案。

4 个答案:

答案 0 :(得分:5)

在haproxy中实现WebSocket并不困难,不过我承认在这方面找到doc并不容易(希望这个响应会举一个例子)。如果你正在使用haproxy 1.4(我想你是这样),那么它就像任何其他HTTP请求一样工作,而不必做任何事情,因为haproxy可以识别HTTP升级。

如果要将WebSocket流量定向到与其余HTTP不同的服务器场,那么您应该使用内容切换规则,简而言之:

 frontend pub-srv
    bind :80
    use_backend websocket if { hdr(Upgrade) -i WebSocket }
    default_backend http

 backend websocket
    timeout server 600s
    server node1 1.1.1.1:8080 check
    server node2 2.2.2.2:8080 check

 backend http
    timeout server 30s
    server www1 1.1.1.1:80 check
    server www2 2.2.2.2:80 check

如果您正在使用1.5-dev,您甚至可以指定“超时隧道”以使WS连接的超时比正常HTTP连接更长,从而使您无需在客户端使用过长的超时。

您还可以组合升级:WebSocket +特定网址:

 frontend pub-srv
    bind :80
    acl is_websocket hdr(Upgrade) -i WebSocket
    acl is_ws_url path /something1 /something2 /something3
    use_backend websocket if is_websocket is_ws_url
    default_backend http

最后,请不要使用我们有时看到的愚蠢的24小时空闲超时,它绝对没有 现在就建立会议等待客户24小时的感觉。网络更多 移动比80年代和连接都非常短暂。你最终会得到许多FIN_WAIT套接字 徒劳无功。目前的互联网已经有10分钟了。

希望这有帮助!

答案 1 :(得分:0)

WebSockets不能很好地遍历代理,因为握手之后它们没有遵循正常的HTTP行为。

尝试使用WebSocket(wss://)协议(安全WS)。这将使用代理CONNECT API,它将隐藏WebSocket协议。

答案 2 :(得分:0)

我使用https://launchpad.net/txloadbalancer与Tornado websocket处理程序进行负载平衡。它很简单,效果很好(我认为)。

答案 3 :(得分:0)

http nginx(仅限nginx v1.3 +)

upstream chatservice {
    #multi thread by tornado
    server 127.0.0.1:6661;
    server 127.0.0.1:6662;
    server 127.0.0.1:6663;
    server 127.0.0.1:6664;
}
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

虚拟主机

server {
    listen 80;
    server_name chat.domain.com;
    root /home/duchat/www;
    index index.html index.htm;

    location / {
            try_files $uri $uri/ @backend;
    }
    location @backend {
            proxy_pass_header Server;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_pass http://chatservice;
            internal;
}