使用HAProxy将负载平衡WebSocket连接到Tornado应用程序?

使用HAProxy将负载平衡WebSocket连接到Tornado应用程序?,proxy,nginx,websocket,tornado,haproxy,Proxy,Nginx,Websocket,Tornado,Haproxy,我正在开发一个使用websocket处理程序的Tornado应用程序。我正在使用Supervisord运行多个应用程序实例,但在负载平衡websocket连接时遇到问题 我知道nginx不支持即时处理websocket,但我按照这里的说明使用nginx tcp_代理模块来反转代理websocket连接。但是,这不起作用,因为模块无法路由websocket URL(例如:ws://localhost:80/something)。因此,它无法与我在Tornado应用程序中定义的URL路由一起工作 从

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

我知道nginx不支持即时处理websocket,但我按照这里的说明使用nginx tcp_代理模块来反转代理websocket连接。但是,这不起作用,因为模块无法路由websocket URL(例如:ws://localhost:80/something)。因此,它无法与我在Tornado应用程序中定义的URL路由一起工作

从我对web的研究来看,HAProxy似乎是平衡websocket连接负载的方法。然而,我很难找到任何合适的指南来设置HAProxy以实现websocket连接的负载平衡,并能够处理websocket URL路由


我真的很感激一些关于如何进行这项工作的详细说明。我也对其他解决方案持完全开放态度。

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


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

在haproxy中实现WebSocket并不困难,尽管我承认在这方面还不容易找到文档(希望此响应将提供一个示例)。如果您使用的是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 前端酒吧 绑定:80 如果{hdr(升级)-i websocket} 默认后端http 后端websocket 超时服务器600s 服务器节点1.1.1.1:8080检查 服务器节点2.2.2.2:8080检查 后端http 服务器超时30s 服务器www1 1.1.1.1:80检查 服务器www2 2.2.2.2:80检查 如果您使用的是1.5-dev,您甚至可以指定“timeout tunnel”,使WS-connections的超时时间大于普通HTTP连接的超时时间,从而避免在客户端使用过长的超时时间

您还可以将Upgrade:WebSocket与特定URL结合使用:

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 前端酒吧 绑定:80 acl是\u websocket hdr(升级)-i websocket acl是\u ws\u url路径/something1/something2/something3 如果是,则使用后端websocket 默认后端http 最后,请不要使用我们有时会看到的愚蠢的24小时空闲超时,这绝对是不可能的 立即使用已建立的会话等待客户机24小时。网络要多得多 与80年代相比,移动和连接都是非常短暂的。你最终会有很多个FIN_等插座 白白的。10分钟对于目前的互联网来说已经相当长了

希望这有帮助

我曾经使用Tornado websocket处理程序进行负载平衡。它很简单,而且运行良好(我认为)。

HTTPNginx(仅限nginx v1.3+) 虚拟主机
那么你是说如果我使用WSS://那么url处理就可以实现?我不同意,事实上恰恰相反,握手是100%符合HTTP的,并且是为此而设计的,但是它使用了HTTP的升级功能,而在过去,许多代理并不关心实现这一功能。如果您的代理不支持升级机制,请向您的供应商提交错误报告,这对于修复web非常重要!是的,Amir,WSS绕过了代理需要从升级中实现的逻辑。它使It在不进行任何干预的情况下处理背对背的连接。感谢您提供的详细且信息丰富的回复。我今天会试试,然后回来汇报。我知道您表示不喜欢高空闲超时,您的观点对大多数应用程序都有意义。我实际上使用WebSocket在嵌入式设备和服务器之间创建通信。该设备实际上将永远处于开启状态(理论上)。那么有没有一种方法可以完全不超时呢?@AmirR。我也希望实现一个类似的设置,希望听到你的结果,采用上述答案。你可以禁用超时,如果你想(并将得到警告)。但这始终是一个设计错误,因为您假设设备永远不会出现故障/崩溃/重新启动/断开连接,这是100%错误的。请记住,存在超时是为了保护一个组件不受另一个组件意外故障的影响。当你的设备出现故障时,你不想重新启动haproxy来摆脱fantom连接,这是没有意义的。
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;
}