Linux的集群类型大体分为LB、HA、HP
其中LB集群是以N台主机提供相同服务,由一台主机作为负载均衡调度器,这些主机共同组成的计算机集合叫做负载均衡集群。如下图所示
其中,最主要的是调度器的实现:
工作在协议层次来划分:
(1)TCP:根据请求报文总的目标地址和端口进行调度;
(2)应用层:根据请求的内容进行调度,且此种调度为“代理”方式.
具体的实现方式有软件和硬件两种方式
(1) 基于软件的实现方式有以下几种:
tcp:lvs (Linux Virtual Server), haproxy, nginx
http:haproxy, nginx, apache(proxy module, balancer module), ats(apache trafficserver), squid, varnish
mysql:mysql-proxy
(2)基于硬件的实现方式有以下几种:
F5:Big-IP
Citrix:NetScaler
A10:A10
Array:Array
RedWare
下面具体说以下LVS(Linux Virtual Server)
LVS被称为4层交换(layer4router或layer4 router),是基于4层协议根据目标地址和端口作出转发与否的决策,根据调度方法作出转发至哪一个后端的决策。所支持的协议有TCP、UDP、SCTP(流控制传输协议)、AH(验证头协议)、ESP(有效载荷)、AH_ESP。
由于在linux中传输层是工作在内核中,所以LVS是工作在内核中,实际上LVS由两部分组成:
Ipvs:是LVS中真正工作在内核中的部分,工作在netfiler的基础上,下面用图例说明ipvs的工作机制
如图所示:
Ipvs会将发送给用户某个端口的请求,在input链上强制转发出来送给后端的主机,而对其他端口的请求不做定义。
Ipvsadm则用于在ipvs上定义集群服务:同时也得定义此集群服务对应于有哪个后端主机可用,根据所指定的调度方法(算法)作出调度决策。
如果很难理解的话可以将ipvsadm和ipvs比作iptables和netfilter,这样就更好理解了。
下面介绍一个LVS中的相关术语:
Host:
Director:调度器
Real Server: RS,后端提供服务的主机
IP:
Client:CIP用户发送请求的IP地址(图中1)
DirectorVirtual IP(flowing IP): VIP提供虚拟服务的IP(图中2)
DirectoryIP: DIP用来和后端主机通讯的IP(图中3)
RealIP: RIP实际提供的IP(图中4、5)
明白了基本术语,下面就开始介绍LVS的类型了(非!常!重!要!)
(1) lvs-nat(基于NAT模型实现)或叫masquerade(地址伪装)以目标地址转换的方式来实现,支持多目标转发.
当client访问director时,源地址为CIP目标地址为VIP,当进入director时,由ipvs将请求的目标地址路由成RIP,再由director的调度算法计算出后端特定服务器接受请求,然后发给实际提供服务的real server,响应报文回应给director时,源地址为RIP目标地址为CIP,到达director后将RIP路由成VIP,最终由director返回给client。
注意:客户端访问的是VIP,所以必须由VIP响应。
架构特性:
#RS应该使用私有地址,即RIP应该为私有地址;各RS的网关必须指向DIP;
#请求和响应报文都经由Director转发;高负载场景中,Director易于成为系统瓶颈;
#支持端口映射;
#RS可以使用任意类型的OS。
#RS的RIP必须与Director的DIP在同一网络;
(2) lvs-dr 或称为directrouting(直接路由)
它的工作流程为,由client发送源地址CIP目标地址VIP的请求经过层层路由到达director,由director中的规则,将请求调度给指定的real server,最后由real server直接响应给client而不经过director。
这里要注意的是,既然是由real server直接响应给client,那么响应时的源地址应该为VIP,目标地址为CIP,说白了就是请求哪个地址就最终由哪个地址响应。
那么这样说来,交换机后面的三个主机都需要配VIP才可以,而且要保证请求到达时一定要由director接收,而三体主机的地址都相同,就需要前端路由器通过ARP解析后(标记上MAC地址)发给director,director收到请求后在转发时将源地址标记上自己的MAC地址,目标地址标记上real server的MAC地址,最终通过交换机发给real server,real server接收到请求时将源MAC地址和目标MAC地址拆封后,仅剩下CIP和VIP,这样,就可以通过real server返回响应报文给client,从而不经过director。
所以说,dr模型不是通过修改目标IP来转发报文,而是通过修改目标MAC来实现的报文转发。
但是director和real server的DIP和RIP依然存在,所以,就需要在DIP的网卡别名上添加一个VIP即可,在real server的本地回环地址的别名上配置VIP。由于linux在发送请求的时候标记的源地址一定是物理网卡的地址,所以当请求到达real server时,由RIP接收请求通过内部的forward链将请求转换发,同时硬性添加上lo上的VIP,就可以出去啦。
DIP、RIP和VIP也可以不在一个网段里哦,只要所有DIP、RIP指向一个网关,所有VIP指向一个网关即可,这样可以减少前端路由器的负载。
架构特性:
#保证前端路由器将目标地址为VIP的请求报文通过ARP地址解析后送往Director
解决方案:
静态绑定:在前端路由直接将VIP对应的目标MAC静态配置为Director的MAC地址;
arptables:在各RS上,通过arptables规则拒绝其响应对VIP的ARP广播请求;
内核参数:在RS上修改内核参数,并结合地址的配置方式实现拒绝响应对VIP的ARP广播请求;
#RS的RIP可以使用私有地址;但也可以使用公网地址,此时可通过互联网上的主机直接对此RS发起管理操作;
#请求报文必须经由Director调度,但响应报文必须不能经由Director;
#各RIP必须与DIP在同一个物理网络中;
#不支持端口映射;
#RS可以使用大多数的OS;
#RS的网关一定不能指向Director;
(3) lvs-tun或称为tunneling(基于隧道做转发)
前两种由于都是在统一网段中,具有一定的地域限制,在异地容灾备份时就束手无策。Tunneling突破了这种限制,director和real server可以远隔千山万水,实现异地的调度。具体实现方式如下:
Client发送报文经过互联网到达director,director调度给远隔千里的realserver ,最终由real server直接回应给client。由于这里的所有IP均为公网IP,client发送的报文源地址为CIP,目标地址为VIP,所以最终real server回应给client的报文中,源地址也应该为VIP,目标地址为CIP。既然图上所述的director和real server都有VIP,那么就会采取一些机制保证director为唯一可访问的VIP,而且,由于real server直接回应给client请求,所以real server接收到的director的请求中,源地址应该是CIP,目标地址是VIP,但director和real server也是在公网上通讯的,通讯的源地址只能是DIP和RIP。那么,把含有CIP、VIP的请求装入含有DIP、RIP的请求内,就可以实现IP隧道承载IP报文的隧道式发送。这里可以想象成,把数据比作行李,把CIP、VIP报头比作行李箱,DIP、RIP报头比作轮船,从director发给远在大洋彼岸的real server。
架构特性:
#RIP,DIP, VIP都是公网地址;
#RS的网关不能,也不可能指向DIP;
#请求报文由Director分发,但响应报文直接由RS响应给Client;
#不支持端口映射;
#RS的OS必须得支持IP隧道;
(4) lvs-fullnat(现在的内核默认不支持,必须到fullnat的官方站点下载源码重新编译内核才能得以实现,ipvsadm默认也不支持)
Fullnat模型解决了在集群内同一物理网络中不能实现网络复杂化的束缚。
具体实现方式为,client发送请求给director,director经过ipvs的处理转发给后端real server中,real server处理完请求响应给director,再由director回应给client。可以将此模型看做是扩展型的nat。只不过相对于nat模型,在director与real server间的数据发送和接收有所差别,由于在内部是经过几个路由转发的,所以real server不能像nat模型一样将网关直接指向director,从而直接改动目标地址即可。而是director收到client的报文,将CIP、VIP路由成DIP、RIP,这样,就可以在内部能够跨越多个路由发送和接收数据了。
架构特性:
#RIP,DIP可以使用私有地址;
#RIP和DIP可以不在同一个网络中,且RIP的网关未必需要指向DIP;
#支持端口映射;
#RS的OS可以使用任意类型;
#请求报文经由Director,响应报文经由Director;
以上四种就是LVS的类型
接下来说一下LVS的调度类型(lvs scheduler),共有十种:可以使用如下命令查看
静态方法:仅根据算法本身实现调度;(调度的起点公平)
RR:round-robin, 轮询;轮叫、轮调、轮流;是最简单的调度方式。
WRR:weightedround-robin, 加权轮询;通过给每一个real server指定权重,权重越大,则承载能力越强,权重计算公式overhead=conn/weight
SH:Source ipHashing,源地址哈希;当用户发送请求到director,在director内部有一段内存空间,把每一个请求中的源地址抽取出做哈希计算,如果此IP地址从未访问过director,就直接根据算法做RR或WRR做轮询,并把访问到的后端主机地址加到director中的哈希表中,此IP再次访问就直接调度给上次此IP地址访问的后端主机。所以所有访问都是先经过此哈希表再通过算法轮询。简化来说就是调度把来自同一个地址请求,统统定向至此前选定的RS。这样就损害了负载均衡的效果,但是却实现了会话绑定。
DH:Destinationip Hashing, 对目标地址哈希;把访问同一个目标地址的请求,统统定向至此前选定的某RS;举例说明:如一个公司内有两个缓存服务器,做成集群,用户访问外网前首先要经过director,由director将请求调度给两个缓存服务器,缓存服务器将向外网请求的页面缓存在服务器中,而且通过目标地址做哈希计算实现会话绑定。但弊端是会造成单一real server负载过大。
动态方法:根据算法及后端RS当前的负载状况实现调度,计算结果overhead值小,则作为下次调度的目标;(调度的结果公平)
LC:least connection(最少链接):其中,第一次请求时,所有服务器的负载都是0,则根据director中指定的顺序发送请求,第二次请求时开始按照调度算法分配,算法如下:
Overhead=Active(活动链接)*256+Inactive(非活动链接)
WLC:weighted least connection(加权后的最少链接)算法如下:
Overhead=(Active*256+Inactive)/weight(权重)
SED:Shorted ExpectionDelay(最短期望延迟)这种算法相对于WLC算法在每一次的分配上更具有指向性,但存在的问题是,如果几台real server的权重差值较大,则可能会造成其中某一台real server负载很小,而其他real server 负载很大,算法如下:
Overhead=(Active+1)*256/weight
NQ:Never Queue(非排队)是对SED算法的一种改进,在分配请求前每个real server都分配一个请求,接下来的请求则按照SED算法调度。
LBLC:Local-BasedLeast Connection(基于本地的最少链接),动态方式的DH算法;是在HD算法的基础上,当real server1负载过大时,动态调度到real server2上,而这real server2需要重新向外网请求页面,再缓存到服务器,这样就造成了时间浪费。
LBLCR:ReplicatedLBLC(带复制的基于本地的最少链接)是在LBLC的基础上,当real server1负载过大时,将real server1中的缓存同步到real server2中,当请求被调度到real server2上时,直接请求缓存即可,无需重新想外网请求页面。
而ipvs中默认的是WLC调度方法,因为调度方法既考虑了当前主机的活动链接状态又考虑了非活动链接状态,虽然SED和NQ都在WLC基础上有所改进,但这种改进所带来的收益微乎其微,所以现今使用多为WLC算法。
以上这些就是LVS中LB集群的一些基本理论。
如有偏颇,望指正。