kaikeba

WebSocket连接的负载均衡

本文由码农网 – 郝林伟原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划

当管理大系统时,负载均衡的问题一直是一个热点话题。负载均衡的目的是最优化资源使用,最大化吞吐量,最小化响应时间,避免任何单一资源的过载,因而解决这个问题对性能表现是很关键的。在本文中我们将看一看针对这个问题的一些解决方法。

为了更好的理解WS负载均衡,让我们深入了解一下TCP套接字的背景知识。默认地,一个单独的服务器可以处理65536个套接字连接,因为65536是可用的最大的TCP端口数。因此,既然WS连接拥有TCP的特性,每个WS客户端占用一个端口,我们可以肯定地说WebSocket的连接数目也是有限的。

事实上,这只说对了一半。对每个单独的IP地址,服务器都可以处理65536个套接字。因而通过向服务器上添加额外的网络接口,就很容易扩展那个数量。与此同时,去追踪服务器上现有多少链接是极其重要的。一旦超出了限制范围,你会遇到很多关于TCP连接的问题(例如,此时不可能通过ssh去连接到一个服务器)。因而,在你的应用程序代码中限制每个节点的WS连接数是很好的主意。当我们处理WebSockets问题时也会在我们的apps中使用一样的思路。

一旦我们理解了主要的限制条件,以及解决方式之后,让我们开始考虑负载均衡。下面我将描述在我们自己的项目中试过的三种方式。请注意所有的系统部分都是部署在AWS上的,其中的一些技巧和提示只适用于Amazon配置。

ELB方法

实现负载均衡最简单的办法是直接使用AWS提供的Elastic Load Balancer方法。从ELB切换到TCP模式是很容易的,这就使得任何类型的TCP连接的负载均衡成为可能, 包括WebSockets。这个方法有如下特性:

  • LB的自动故障恢复;
  • 负载均衡节点的自动伸缩;
  • 非常简单的设置。

基本上,对大多数情况而言它是一个很好的解决方案,在你遇到负载飞溅的增长情况之前。在这种情况下,ELB运行的很慢以至于无法建立新的连接。可以去联系Amazon,告诉他们去“预热(pre-warm)”ELB,但是它对我们不是一个好的选项,基于负载测试的目的,当我们需要快速建立成千上万的WS连接时;对客户也不是好选项,基于系统的可用性。

软件负载均衡器

我们曾经试过使用HAProxy作为一个负载均衡器。但是为了使HAProxy正确工作我们需要考虑上文讨论的端口限制问题。为了使HAProxy能够处理超过65536个链接,我们需要执行下面步骤:

1.创建一堆私有的IP地址。为了实现这个目的,选择Amazon Instance -> Actions -> Networking -> Manage Private IP Addresses,我们添加三个IP地址:192.168.1.1,192.168.1.2,192.168.1.3。切记,IP要处于与你的真实应用程序服务器同样的子网中;

2.使用SSH连接到你的HAProxy实例,执行下面的命令:

$> ifconfig eth0:1 192.168.1.1
$> ifconfig eth0:2 192.168.1.2
$> ifconfig eth0:3 192.168.1.3

这些命令会往实例中添加3个虚拟网络接口;

3.配置HAProxy。这里是haproxy.cfg文件中的一段,用于3个Erlang节点接收WS连接。

listen erlang_front :8888
    mode        http
    balance     roundrobin
    timeout connect 1s
    timeout queue 5s
    timeout server 3600s
    option httpclose
    option forwardfor
    server      erlang-1 192.168.0.1:8888  source 192.168.1.1
    server      erlang-2 192.168.0.2:8888  source 192.168.1.2
    server      erlang-3 192.168.0.3:8888  source 192.168.1.3

现在,HAProxy能够处理超过65536个WebSockets链接,通过增加虚拟网络接口,连接限制可以简单地增长。同时,它也能非常快地建立新连接。这个方法看上去可行,尽管它有如下缺点:

  • 故障恢复的HAProxy实例需要使用类似Keepalived工具去手动建立;
  • 每次你增加一个新的Erlang节点,都要做些操作去重新配置HAProxy;
  • 随着连接数目增长,没有能水平伸缩HAProxy的选项。我们只有一个垂直选项可用,因此当我们有了越来越多的在线用户后,我们需要越来越多的昂贵的HAProxy实例(以及HAProxy镜像节点)。

对这些缺点我们也还觉得满意,但是一个更简单的方案已经被实现了。那是可能的,因为我们已经有了一些实现好的代码,而我们的系统设计也允许我们使用一个定制方法。

定制方法

在继续前进之前,我们先回顾一下下面的图,它显示了我们系统的架构。

我们拥有一个JavaScript客户端应用程序,一个auth应用负责用户授权,一个Erlang应用实现主要的功能。数据流如下:

1.客户端生成一个含有凭证的HTTP请求,发送给Auth Application;

2.Auth Application检查凭证,生成一个令牌,以一种HTTP请求的形式将它发送给Erlang Cluster;

3.Erlang应用确认,令牌已经收到,给Auth应用返回一个包含配置信息的HTTP响应;

4.Auth App给客户端应用程序发送一个HTTP响应。响应中包含生成的令牌;

5.客户端使用令牌通过我们的HAProxy负载均衡器建立与Erlang应用之间的WebSocket连接。

这是我们基本的数据流,它被稍微修改了一点。我们添加一个简单的模块到Erlang应用程序中去追踪每个Erlang节点上的WebSocket连接数。基于Erlang“分布式的”特性,每个节点可以知道其它节点的连接数。因而,我们可以选择一个拥有更少连接的节点,我们使用这个节点的公共IP地址,把它发送回那个auth应用程序。然后那个auth应用程序将这个IP地址随令牌返回到客户端。客户端使用接收到的IP地址和令牌去建立连接。因而,最终的图显示如下:

现在我们能够:

  • 去掉WS负载均衡器,这就使得我们的系统变得不是那么复杂;
  • 添加Erlang节点,而不用对系统其它部分进行重新配置。

除此之外:

  • 现在WS连接是平均分布于Erlang节点之间的;
  • 系统很容易水平伸缩;
  • 对Erlang节点我们不需要使用Elastic IPs。

译文链接:http://www.codeceo.com/article/websocket-load-balanced.html
英文原文:Load Balancing of WebSocket Connections
翻译作者:码农网 – 郝林伟
转载必须在正文中标注并保留原文链接、译文链接和译者等信息。]

发表我的评论

取消评论
表情 插代码

Hi,您需要填写昵称和邮箱!

  • 必填项
  • 必填项