“软”负载均衡

需求转而学习

很多时候不少做开发的同学都认为技术更新的快,新技术、新概念层出不穷,大家乐此不疲的去跟随着所谓的“技术趋势”走在风头浪尖上,但其实往往忘记了一个最重要的问题“满足客户需求”。其实技术就是为满足需求服务的,用最小的代价来满足用户的需求,以最简单高效的方式来达到目标,就是每个开发者应该追求的。(不要因为自己的架构很简单就脸红拿不出手,只要你在满足用户当前需求的基础上对未来有所考虑,那么化繁为简就是一种能力的表现)

SIP(服务集成平台)5.7版本中对于未来多个服务提供商,多种类型的服务,在每日几亿的调用压力下,需要找到一个解决方案:可以分流不同服务提供商的服务,分流不同类型的服务,服务隔离化来减少服务相互之间影响以及服务提供商之间的影响。

当前SIP的前端是通过硬件F5作负载均衡,因此是无状态无差别的服务负载,这也使得无法区分不同的服务提供商的服务请求和不同类型的服务请求,导致服务提供商之间的服务会产生相互影响(旺旺即时通信类API在峰值占用了大部分的服务处理资源,淘宝宝贝上传类API占用了大量的带宽)。近期还有更大的两类API将会接入,因此寻找一个服务可分流的方案势在必行。(当然过去也考虑通过三级域名配置在负载均衡上来解决这些问题,但是这样首先对于开发者来说不透明,其次也是一种比较僵化的设计方案,扩展和维护也有一定的难度)

在过去也尝试过Apache等Web容器自己的一些load balance特性,当然效果不是很好,和硬件基本无法比拟,而一些专有的“软”负载均衡方案和开源项目也没有深入的去了解,因此借着这次机会,好好深入的挖一挖“软”负载均衡。

“软”负载均衡          作为互联网应用,随时都需要做好用户量突然增大,访问量突然上升的准备。今年热门的词汇“云”我就不多说了,这里就简单说说服务器的横向扩展。其实和DB,文件系统等一样,当资源成为瓶颈的时候,就需要考虑如何通过扩展或者提升资源能力来满足用户的需求,这就是我们常说的横向扩展和纵向扩展。(对于横向扩展和纵向扩展的优劣大家应该都很清楚了,这里也不做赘述)横向扩展中就会要求使用负载均衡的能力,如何根据资源能力不同以及资源在运行期负荷动态变化将负载合理分配是判断负载均衡优劣的标准。

软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第三方应用的软负载实现。LVS就是基于Linux操作系统实现的一种软负载,HA Proxy就是基于第三应用实现的软负载。(后面会详细介绍这两种方式的使用)

最早期也是最原始的软负载均衡:“Round Robin DNS”,通过轮询方式在DNS绑定多个IP的情况下,将用户对于同一个域名的请求分配到后端不同的服务节点。这种方案的优点:配置简单,负载分配效率高。缺点:无法知晓后端服务节点服务情况(是否已经停止服务),无法保证在一个Session中多次请求由一个服务节点服务,每一个节点都要求有一个外网IP。

另一种较为常见的就是基于分发器的Load balance。服务使用者通过向分发器发起请求获得服务,分发器将请求分发给后端实际服务处理的节点,给客户提供服务,最常说的反向代理模式就是典型的分发器Load Balance。这类负载均衡处理可以基于应用级转发,也可以基于IP级别转发,当然基于应用转发效率和损耗比较大,同时分发器本身也会成为瓶颈。

 

LVS (Linux Virtual Server)          LVS是在Linux操作系统基础上建立虚拟服务器,实现服务节点之间的负载均衡。LVS主要是处理OSI模型中的4层消息包,根据一定的规则将请求直接转发到后端的服务处理节点,有较高转发效率。

Virtual Server是Load Balancer和一组服务器的逻辑组合统称,使用服务者只需要与Virtual Server进行交互就可以获得高效的服务。真实服务器和Load Balancer通过高速LAN进行交互。Load Balancer能够将请求分发到不同的服务端,在一个虚拟IP下并行处理多个请求。

Virtual Server三种模式介绍

Virtual Server有三种基于IP级别的负载均衡实现方式:IP address translation(NAT)、Direct routing、IP Tunneling。

NAT(Network address translation):由于IPV4的某些缺陷和安全原因,某些网段例如(10.0.0.0/255.0.0.0, 172.16.0.0/255.240.0.0 and 192.168.0.0/255.255.0.0)不能被用于互联网,因此常常被用作内部局域网,通过网络地址翻译的方式可以让这些网段的服务器访问互联网或者被互联网访问。网络地址翻译主要作用就是将一组ip地址映射到其他的一组ip地址,当映射比例为1:1的时候通常称作静态映射,而当映射地址为M:N(M>N)的时候(M为被映射地址数量,通常是内部ip),则成为动态映射。而对于Virtual Server的NAT模式来说,就是利用了NAT的特性,将内部的一组服务器通过映射到一个虚拟的IP,然后以一个外网虚拟服务节点的身份对外提供服务。

上图是一个实际的NAT范例,对外的服务IP为202.103.106.5,内部建立了虚拟IP为172.16.0.1,然后将内部其他两台实际服务的服务器172.16.0.2,172.16.0.3映射到172.16.0.1这个虚拟IP。客户端向202.103.106.5发起请求服务,Load Balancer查看请求数据包,如果是请求目标地址是注册的虚拟IP及监听端口的时候,那么通过NAT按照一定算法选择某一台实体服务器,再重写报文目标地址,转发请求到实际的目标服务器,当目标服务器处理完毕以后,将处理结果返回给Load Balancer,由Load Balancer修改源地址,返回给客户端。

IP Tunneling:IP管道技术是在IP报文上再次封装IP报文协议的一种技术。允许将一个目标为A的IP数据报文封装成为目标为B的IP数据报文,在特定的IP 管道中传输。

上图就是IP Tunneling模式的运作原理。首先客户端还是通过访问对外的一个服务IP请求服务,当Load Balancer接受到请求以后,检查VIP注册信息,然后根据算法选择实际的一台后台服务器,通过IP管道封装技术对IP报文再次封装,然后将消息通过IP管道转发到实际的服务器,实际的服务器通过解包处理请求,然后根据包体内实际的服务请求地址,将处理结果直接返回给客户端。

Direct routing:利用Load Balancer和实际服务器共享同一VIP,简单的通过修改消息报体目标MAC地址,转发请求,然后再通过实际服务器配置VIP为本地回环,直接处理消息报文,而不再转发,当处理完以后,直接将处理结果返回给客户端。

上图就是Direct Routing的运作流程,当外部请求到Load Balancer时,通过查找VIP注册信息,直接选择一台后端服务器作为新的目标地址,修改消息报文中的目标地址Mac地址,转发到目标服务器,目标服务器由于配置VIP在本地网卡回路中,因此直接处理消息,将处理完的结果直接返回给客户端。

Virtual Server三种模式的比较

下表是官方整理出的关于Virtual Server三种不同模式的区别:

NAT TUNNEL DR
服务器要求 无要求 需要支持IP管道 无 arp组件(当前也有补丁)
网络要求 Private LAN/WAN LAN
可支持后端服务器节点数 较少(10-20) 较多 较多
服务网关 Load Balancer 本身 本身

NAT:根据其实现原理,可以知道这种模式对于操作系统,网络都没有太多的要求和约束,但是由于消息需要打解包,同时消息的响应都必须经过Load Balancer,因此Load Balancer自身成为了瓶颈,这样一个Load Balancer能够支持的后端服务节点数量就有限了。当然可以采用混合模式来解决这个问题,也就是通过TUNNEL或者DR模式作为前端模式串联起多个NAT模式Balancer。

TUNNEL:这种模式要求操作系统支持IP Tunnel,通过对IP报文再次封装转发,达到负载均衡的目的。设计这种模式的初衷是考虑,对于互联网很多服务来说,服务请求数据量和返回数据量是不对称的,返回的数据往往要远远大于请求的数据量,因此如果请求和返回都走Load Balancer会大量占用带宽,影响处理能力。IP Tunnel设计中请求是通过Load Balancer,但是返回是直接返回到客户端的,因此节省了返回的带宽,提高了请求处理的能力。

DR:这种模式要求Load Balancer和后端服务器处于同一个局域网段。DR模式处理消耗最小,消息转发和回复基本没有损耗,因此效率应该是最高的,但是约束是相对来说最多的。

Virtual Server三种模式实践

服务器资源:

10.2.225.128作为Load Balancer,10.2.225.136和10.2.225.139作为后端的服务器。

在10.2.225.136和10.2.225.139上分别安装Apache2.2.14,然后打开80端口,启动Web服务。

1.  安装LVS配置工具(只需要在Load Balancer安装即可)

Linux操作系统当前大部分都已经支持Virtual Server,因此不需要再去编译内核,只需要下载和安装用户配置工具ipvsadmin。首先请查看自己Linux操作系统内核的版本,我的版本是2.6.18。从http://www.linux-vs.org/software/ipvs.html#kernel-2.6 下载了ipvsadm-1.24.tar.gz。安装步骤如下:

# tar –xzvf ipvsadm-1.24.tar.gz

# ln –s /usr/src/kernels/2.6.18-128.el5-i686 /usr/src/linux  (这部必须作,因为在编译和安装的时候需要用到目录/usr/src/linux来获得必要的外部依赖库)

# cd ipvsadm-1.24

# make && make install

输入ipvsadm,如果看到以下内容证明安装成功了:

IP Virtual Server version 1.2.1 (size=4096)

Prot LocalAddress:Port Scheduler Flags

-> RemoteAddress:Port           Forward  Weight  ActiveConn  InActConn

2.  DR模式测试

a.       为10.2.225.128这台Load Balancer的网卡绑定虚拟IP。

ifconfig eth0:0  10.2.225.211  netmask 255.255.255.0  broadcast 10.2.225.211  up

b.       在Load Balancer上建立虚拟IP。

Ipvsadm –A –t 10.2.225.211:80 –s rr  //221 IP没有实体机器在使用,因此作为虚拟IP使用,A表示建立虚拟IP,t表示是tcp协议,s表示负载算法,rr是Round Robin。

c.       在Load Balancer上建立虚拟IP与两个实体服务器的关系。

ipvsadm -a -t 10.2.225.211:80 -r 10.2.225.136:80 -g -w 1  //将虚拟IP和端口关联到实体机器上,a表示新建虚拟IP和实体机器的关联关系,r后面跟实体机器地址和端口,g表示使用DR模式,w是权重。

ipvsadm -a -t 10.2.225.211:80 -r 10.2.225.139 :80 -g -w 1

d.       在另外两台实体服务器上建立虚拟IP与网卡回环的绑定关系。

ifconfig lo:0  10.2.225.211  netmask  255.255.255.255  broadcast  10.2.225.211  up

下图就是配置好以后再输入ipvsadm查看到的虚拟配置信息
         其中Route表示就是DR的模式,然后图中ActiveConn表示连接数,这里是访问一个发布在两台后端服务器的页面带来的连接数,访问页面的情况如下两张图:(主要是看返回页面中服务器ip打印的不同)

访问页面的结果和DR是一样的,对虚拟IP的访问,会轮询到不同的后端服务器上。

三种模式下的简单压力测试

简单的压力测试采用Apache ab,500并发用户,10w的请求总数。

总耗时(s) TPS(#/sec)
NAT 22.480 4448.34
TUNNEL 10.707 9339.80
DR 10.177 9825.68

可以看出NAT性能要比后两种差一倍。

LVS是从四层对消息进行负载转发的,很大程度上是直接利用操作系统的特性来实现消息转发,因此转发损耗有限,但是NAT模式中Load Balancer对于性能的影响很大,同时对于负载压力本身以及后台节点数目有限制。在LVS基础上有很多其他的开源软件,增加了心跳等机制来保证集群的健壮性。而LVS并不能满足根据应用参数或包体内容转发请求的场景,因此进一步研究HA-Proxy,这种基于基于应用级别在7层对消息作分析转发的负载均衡方案。

HA-Proxy

          HA-Proxy相比LVS的使用要简单很多,功能方面也很丰富。HA-Proxy可以在4,7两层作负载均衡,4层大多用于邮件服务器、内部协议通信服务器等作负载均衡,7层用于Http分析负载转发。

在HA-Proxy官方网站可以下载配置说明文档(configuration.txt)和架构文件(architecture.txt)作为参考。具体的使用细节不做太多介绍,这里主要通过具体的配置来大致说一下HA-Proxy的结构。

HA-Proxy 组件图

HA-Proxy配置中分成四部分内容,当然这些组件不是必选的,可以根据需要选择部分作为配置。Defaults组件是配置默认参数的,这些参数可以被利用配置到frontend,backend,listen组件中(当这些组件某些参数没有被配置而在Defaults中配置了)。Frontend组件是接收请求的前端虚拟节点,就类似于LVS中配置了VIP的Load Balancer,Frontend可以直接指定后端指向那一个backend(可动态选择)。Backend是后端服务集群的配置,类似于LVS中的那些Real Server,一个Backend对应一个或者多个实体服务器。Listen是Frontend和Backend的组合体,可以直接定义一个类似于JBoss的 Server Farm。还有一些默认的配置可以通过在配置文件中配置或者在命令行中作为参数输入。

HA-Proxy安装和使用

安装HA-Proxy:

1.  下载HA-Proxy安装包。

2.  解压执行make TARGET=linux26(注意,TARGET后面根据本机操作系统内核版本来填写)

3.  make install

4.  目录下执行haproxy,如果有使用说明出现表示已经安装正常。

5.  使用方式haproxy –f 配置文件地址。(例如 haproxy –f haproxy.cfg)

 

HA-Proxy日志配置说明:

HA-Proxy可以收集本机及其他后端服务器日志,但是需要在Load Balancer上作一些配置。

首先修改/etc/sysconfig/syslog文件,将SYSLOGD_OPTIONS=”-m 0” 修改为SYSLOGD_OPTIONS=”-m 0 -r -x”,支持收集远程服务器日志。

然后修改/etc/syslog.conf,增加如下语句:

#add by haproxy

local0.*  /home/admin/tools/haproxy-1.3.17/haproxy.log  // haproxy.log地址代表了需要存储日志的地址

执行service syslog restart,重新启动系统日志器

最后就是在HA-Proxy的配置中增加日志输出(具体可以参考后面的配置文件说明)

HA-Proxy配置文件说明:

下面的配置文件简单来说就是配置了根据请求参数的不同,将请求分别定向到后端的淘宝集群和阿里软件集群。具体配置文件(haproxy.cfg)如下:

log 127.0.0.1  local0 info  //日志输出配置,所有的日志都记录在本机,通过local0的系统日志器输出,这关系到前面我们做的配置  
    daemon  //以后台进程方式启动Ha-proxy  
    nbproc 2 //启动两个ha-proxy进程实例  
    pidfile /home/admin/tools/haproxy-1.3.17/haproxy.pid    // pid记录的文件  
 
defaults  //默认配置  
    mode http //默认采用http模式,可以配置tcp来做4层消息转发  
    option httplog //采用http日志格式  
    retries 3 //三次连接失败就认为是服务器不可用,主要是通过后面的check配置来实现服务器状态检查  
    maxconn 2000 //最大连接数  
    contimeout 5000 //连接超时时间  
    clitimeout 50000 //客户端连接超时时间  
    srvtimeout 50000 //服务端连接超时时间  
    stats uri /admin?stats //服务器状态统计查看页面  
    stats auth wenchu:wenchu  //服务器状态查看授权的用户名和密码设置,可以不设置  
    option httpchk HEAD /welcome.html HTTP/1.0  //服务器状态检查设置,这里是向每一个后端服务器请求/welcome.html页面来检查服务端健康状况。  
 
frontend http-in  //前端节点定义  
    bind :8181 //虚拟服务节点监听本地的8181端口  
    mode http   
    log  global  
    option httplog  
    option httpclose //每次请求完毕后主动关闭http通道,HA-Proxy不支持keep-alive模式,只能够模拟这种模式的实现  
    option forwardfor   //如果后端服务器需要获得客户端的真实IP需要配置次参数,将可以从Http Header中获得客户端IP  
    capture request header Host len 20 //此配置和一下的类似配置都是抓取Http请求中的参数记录到日志中。  
     capture request header User-Agent len 16  
    capture request  header Content-Length len 10        
    capture request  header Referer        len 20    
    capture response header Content-Length len 10  
 
    //控制策略的配置  
    acl api_taobao url_sub -i sip_apiname=taobao.  //在请求url中包含sip_apiname=taobao,则此控制策略返回true,否则为false  
    acl api_alisoft url_sub -i sip_apiname=alisoft. //在请求url中包含sip_apiname=alisoft,则此控制策略返回true,否则为false  
    acl invalid_req url_sub -i sip_apiname= //在请求url中包含sip_apiname=,则此控制策略返回true,否则为false  
    acl stat_req url_dir -i admin //在请求url中存在admin作为部分地址路径,则此控制策略返回true,否则返回false  
    block if !invalid_req !stat_req  //block表示阻止请求,返回403错误,当前表示如果不满足策略invalid_req,同时也不满足策略stat_req,则阻止请求。(就是要求URL中必需有参数sip_apiname,除非是查看服务器状态的URL)。  
    use_backend alisoft_server if api_alisoft  //如果是满足策略api_alisoft的情况,则使用alisoft_server作为后端服务集群。  
    use_backend taobao_server if api_taobao //如果是满足策略api_taobao的情况,则使用taobao_server作为后端服务集群。  
    default_backend alisoft_server //使用alisoft_server作为默认后端服务集群。  
 
   
backend alisoft_server //后端节点定义  
   mode http   
   balance roundrobin  //负载均衡策略配置  
   cookie SERVERID  //允许插入serverid到cookie中,serverid后面可以定义  
   server app1 10.2.225.139:80 cookie 1 check fall 5 weight 1  //真实服务器配置定义cookie 1表示serverid为1,check表示需要状态检查,fall 5表示失败五次就认为服务器状态不可用(不在接受请求),weight 1表示权重  
   server app2 10.2.225.136:80 cookie 2 check fall 5 weight 2  
 
backend taobao_server //后端节点定义  
   mode http  
   server app3 10.2.226.41:80 check fall 5   

完成配置后,执行haproxy –f haproxy.cfg,后台进程就可以启动了,然后在浏览器中输入刚才定义的状态检查地址可以看到如下内容:

可以看到定义的前端和后端节点的状态。对于Ha-proxy很多配置这里面都没有使用,也没有详细讲解,使用者可以通过查看官方的配置文档了解细节。下面三个图片分别说明了对于sip_apiname不同的访问产生最后的结果。

上图的sip_apiname为alisoft.get.user,因此被定向到Alisoft集群,也就是136或者139上(这里是136处理了服务)。

上图的sip_apiname为taobao.get.user,因此被定向到Alisoft集群,也就是41上。


上图的sip_apiname没有传递,因此被拒绝访问,返回403错误。

 HA-Proxy的压力测试结果

简单的压力测试采用Apache ab,500并发用户,10w的请求总数。

总耗时(s) TPS(#/sec)
LVS-NAT 22.480 4448.34
LVS-TUNNEL 10.707 9339.80
LVS-DR 10.177 9825.68
HA-2Node 21.387 4675.61
HA-5Node 27.371 3653.37

HA-2Node为配置了两个节点作为后段的服务节点,HA-5Node为配置了5个节点作为后端的服务处理节点。上面结果看到2个节点的HA反而比5个节点的速度来的快,同时HA在7层的转发和LVS-NAT性能相近。

HA-Proxy使用下来,总体上感觉比较简单,但功能却十分强大,但是性能方面来说需要关注在多节点和高压力的情况下的表现。

“软”负载均衡学习心得

从LVS三种模式中也看到了类似于分布式文件系统的一些设计经验,就是避免在管理资源过程中,让Manager成为了系统瓶颈。就好比LVS-NAT中的Load Balancer既负责请求分配同时也负责消息回复,成为了系统的关键节点,自身性能损耗比较大,加上算法对于数据采集的要求,自身稳定性和可用性下降,最后影响了整个架构。在HDFS中,Master的责任就和明晰,就是负责节点管理,不参与数据传输和通道建立,因此就可以很大程度上提升自身的效率。资源管理(申请,归还,状态检查等)和资源使用应该清晰的划分开来,这样可以让各个角色可以更好的独立的满足需求,防止由于其他功能影响到了“本职工作”。

就负载均衡效率来说,硬件实现负载均衡应该优于用软件实现负载均衡,就好比SSL硬件加速器要远优于SSL软件解析模块。但从另一个角度来看,分布式计算,分布式存储,分布式DB都采用横向扩展结合低成本资源的方式满足需求。而软件实现负载在很多情况下可以尽可能的降低成本,同时在性能损失较小的情况下实现硬件负载所支持的所有功能。因此在一定的环境下,部分采用软件来实现负载均衡能够增加可扩展性,提升配置灵活度,降低配置成本。

从LVS到HA-Proxy,可以发现不论从4层做转发还是7层做转发都会存在损失,而且LVS-NAT模式和HA-Proxy都会受到解析负载度和内容大小的影响。因此完全采用软件负载或者采用某一种配置的软件负载都不可行,通过将硬件负载和软件负载相结合,或者多种软件负载混合使用,可以更好的发挥软件负载灵活的优势,同时也不会因为转发损失影响性能。

发表评论