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



我正在开发一个使用websocket处理程序的Tornado应用程序。我正在使用 Supervisord 运行该应用程序的多个实例,但在负载平衡 websocket 连接时遇到问题。

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

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

我真的很感激一些关于如何做到这一点的详细指示。我也对其他解决方案持完全开放态度。

haproxy中实现WebSocket并不难,尽管我承认要找到这方面的文档还不容易(希望这个响应可以举一个例子)。如果您使用的是haproxy 1.4(我想您是),那么它就像任何其他HTTP请求一样工作,而无需执行任何操作,因为HTTP升级是由haproxy识别的。

如果要将 WebSocket 流量定向到与 HTTP 其余部分不同的场,则应使用内容切换规则,简而言之:

 前端发布-SRV    绑定 :80    use_backend websocket if { hdr(Upgrade) -i WebSocket }    default_backend http 后端网络套接字    超时服务器 600s    服务器节点1 1.1.1.1:8080检查    服务器节点 2 2.2.2.2:8080 检查 后端 HTTP    超时服务器 30s    服务器 www1 1.1.1.1:80 检查    服务器 www2 2.2.2.2:80 检查

如果您使用的是 1.5-dev,您甚至可以指定"超时隧道",以便 WS 连接的超时大于普通 HTTP 连接的超时,这样可以避免在客户端使用过长的超时。

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

 前端发布-SRV    绑定 :80    acl is_websocket hdr(Upgrade) -i WebSocket    ACL is_ws_url路径/某物1/某物2/某物3    use_backend websocket(如果is_websocket is_ws_url)    default_backend http

最后,请不要使用我们有时看到的愚蠢的 24 小时空闲超时,它绝对没有感觉现在等待客户端 24 小时并建立会话。网络远不止于此移动比 80 年代和连接非常短暂。你最终会得到许多FIN_WAIT插座白。对于当前的互联网来说,10分钟已经相当长了。

希望这有帮助!

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

尝试使用 WebSocket (

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

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

http nginx (only 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;
}

最新更新