*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
}
.hljs-comment,
.hljs-template_comment,
.diff .hljs-header,
.hljs-javadoc {
color: #998;
font-style: italic;
}
.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.javascript .hljs-title,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #099;
}
.hljs-string,
.hljs-tag .hljs-value,
.hljs-phpdoc,
.tex .hljs-formula {
color: #d14;
}
.hljs-title,
.hljs-id,
.coffeescript .hljs-params,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}
.javascript .hljs-title,
.lisp .hljs-title,
.clojure .hljs-title,
.hljs-subst {
font-weight: normal;
}
.hljs-class .hljs-title,
.haskell .hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rules .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}
.hljs-attribute,
.hljs-variable,
.lisp .hljs-body {
color: #008080;
}
.hljs-regexp {
color: #009926;
}
.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}
.hljs-built_in,
.lisp .hljs-title,
.clojure .hljs-built_in {
color: #0086b3;
}
.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.diff .hljs-change {
background: #0086b3;
}
.hljs-chunk {
color: #aaa;
}
#container {
padding: 15px;
}
pre {
border: 1px solid #ccc;
border-radius: 4px;
display: block;
background-color: #f8f8f8;
}
pre code {
white-space: pre-wrap;
}
.hljs,
code {
font-family: Monaco, Menlo, Consolas, ‘Courier New‘, monospace;
}
:not(pre) > code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
white-space: nowrap;
border-radius: 4px;
}
-->
网站架构中,负载均衡技术是实现网站架构伸缩性的主要手段之一。所谓"伸缩性",是指可以不断向集群中添加新的服务器来提升性能、缓解不断增加的并发用户访问压力。通俗地讲,就是一头牛拉不动时,就用两头、三头、更多头牛来拉。
负载均衡有好几种方式:http URL重定向、DNS的A记录负载均衡、反向代理负载均衡、IP负载均衡和链路层负载。本文所述为LVS,它的VS/NAT和VS/TUN模式是IP负载均衡的优秀代表,而它的VS/DR模式则是链路层负载均衡的优秀代表。
1.LVS简介
LVS中文官方手册:http://www.linuxvirtualserver.org/zh/index.html。这个手册对于了解lvs的背景知识很有帮助。
LVS英文官方手册:http://www.linuxvirtualserver.org/Documents.html。这个手册比较全面,对于了解和学习lvs的原理、配置很有帮助。
LVS是章文嵩开发的一个国产开源负载均衡软件。LVS最初是他在大学期间的玩具,随着后来使用的用户越来越多,LVS也越来越完善,最终集成到了Linux的内核中。有不少开源牛人都为LVS开发过辅助工具和辅助组件,最出名的就是Alexandre为LVS编写的Keepalived,它最初专门用于监控LVS,后来加入了通过VRRP实现高可用的功能。
LVS的全称是Linux virtual server,即Linux虚拟服务器。之所以是虚拟服务器,是因为LVS自身是个负载均衡器(director),不直接处理请求,而是将请求转发至位于它后端真正的服务器realserver上。
LVS是四层(传输层tcp/udp)、七层(应用层)的负载均衡工具,只不过大众一般都使用它的四层负载均衡功能ipvs,而七层的内容分发负载工具ktcpvs(kernel tcp virtual server)不怎么完善,使用的人并不多。
ipvs是集成在内核中的框架,可以通过用户空间的程序ipvsadm
工具来管理,该工具可以定义一些规则来管理内核中的ipvs。就像iptables和netfilter的关系一样。
2.LVS-ipvs三种模式的工作原理
首先要解释的是LVS相关的几种IP:
VIP
:virtual IP,LVS服务器上接收外网数据报文的网卡IP地址。DIP
:director,LVS服务器上发送数据报文到realserver的网卡IP地址。RIP
:realserver(常简称为RS)上的IP,即提供服务的服务器IP。CIP
:客户端的IP。
LVS的三种工作模式:通过网络地址转换(NAT)将一组服务器构成一个高性能的、高可用的虚拟服务器,是VS/NAT技术。在分析VS/NAT的缺点和网络服务的非对称性的基础上,提出了通过IP隧道实现虚拟服务器的方法VS/TUN(Virtual Server via IP Tunneling),和通过直接路由实现虚拟服务器的方法VS/DR(Virtual Server via Direct Routing),它们可以极大地提高系统的伸缩性。
(1).VS/NAT模式
客户端发送的请求到达Director后,Director根据负载均衡算法改写目标地址为后端某个RIP(web服务器池中主机之一)并转发给该后端主机,就像NAT一样。当后端主机处理完请求后,后端主机将响应数据交给Director,并由director改写源地址为VIP后传输给客户端。大多数商品化的IP负载均衡硬件都是使用此方法,如Cisco的LocalDirector、F5的Big/IP。
这种模式下:
- RIP和DIP一般处于同一私有网段中。但并非必须,只要它们能通信即可。
- 各RealServer的网关指向DIP,这样能保证将响应数据交给Director。
- VS/NAT模式的最大缺点是Director负责所有进出数据:不仅处理客户端发起的请求,还负责将响应传输给客户端。而响应数据一般比请求数据大得多,调度器Director容易出现瓶颈。
- 这种模式配置起来最简单。
(2).VS/TUN模式
采用NAT技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。为了解决这个问题,调度器把请求报文通过IP隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务响应报文比请求报文大许多,采用VS/TUN技术后,调度器得到极大的解放,集群系统的最大吞吐量可以提高10倍。
VS/TUN模式的工作原理:
- (1)IP隧道技术又称为IP封装技术,它可以将带有源和目标IP地址的数据报文使用新的源和目标IP进行第二次封装,这样这个报文就可以发送到一个指定的目标主机上;
- (2)VS/TUN模式下,调度器和后端服务器组之间使用IP隧道技术。当客户端发送的请求(CIP-->VIP)被director接收后,director修改该报文,加上IP隧道两端的IP地址作为新的源和目标地址,并将请求转发给后端被选中的一个目标;
- (3)当后端服务器接收到报文后,首先解封报文得到原有的CIP-->VIP,该后端服务器发现自身的tun接口上配置了VIP,因此接受该数据包。
- (4)当请求处理完成后,结果将不会重新交给director,而是直接返回给客户端;在后端服务器返回给客户端数据包时,由于使用的是普通网卡接口,根据一般的路由条目,源IP地址将是该网卡接口上的地址,例如是RIP。因此,要让响应数据包的源IP为VIP,必须添加一条特殊的路由条目,明确指定该路由的源地址是VIP。
采用VS/TUN模式时的基本属性和要求:
- RealServer的RIP和director的DIP不用处于同一物理网络中,且RIP必须可以和公网通信。也就是说集群节点可以跨互联网实现。
- realserver的tun接口上需要配置VIP地址,以便接收director转发过来的数据包,以及作为响应报文的源IP。
- director给realserver时需要借助隧道,隧道外层的IP头部的源IP是DIP,目标IP是RIP。而realsever响应给客户端的IP头部是根据隧道内层的IP头分析得到的,源IP是VIP,目标IP是CIP。这样客户端就无法区分这个VIP到底是director的还是服务器组中的。
- 需要添加一条特殊的路由条目,使得后端服务器返回响应给客户端时的源IP为VIP。
- director只处理入站请求,响应请求由realserver完成。
一般来说,VS/TUN模式会用来负载调度缓存服务器组,这些缓存服务器一般放置在不同网络环境,可以就近返回数据给客户端。在请求对象不能在Cache服务器本地命中的情况下,Cache服务器要向源服务器发请求,将结果取回,最后将结果返回给客户。
(3).VS/DR模式
VS/TUN模式下,调度器对数据包的处理是使用IP隧道技术进行二次封装。VS/DR模式和VS/TUN模式很类似,只不过调度器对数据包的处理是改写数据帧的目标MAC地址,通过链路层来负载均衡。
VS/DR通过改写请求报文的目标MAC地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同VS/TUN技术一样,VS/DR技术可极大地提高集群系统的伸缩性。这种方法没有IP隧道的开销,对集群中的真实服务器也没有必须支持IP隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连在同一物理网段上,以便使用MAC地址通信转发数据包。
VS/DR模式的工作原理:
- (1)客户端发送的请求被director接收后,director根据负载均衡算法,改写数据帧的目标MAC地址为后端某RS的MAC地址,并将该数据包转发给该RS(实际上是往整个局域网发送,但只有该MAC地址的RS才不会丢弃)。
- (2)RS接收到数据包后,发现数据包的目标IP地址为VIP,而RS本身已经将VIP配置在了某个接口上,因此RS会接收下这个数据包并进行处理。
- (3)处理完毕后,RS直接将响应报文响应给客户端。在返回给客户端的时候,由于实用的是普通网卡接口,根据一般的路由条目,源IP地址将是该网卡接口上的地址,例如RIP。因此,要让响应数据包的源IP为VIP,需要添加一条特殊的路由条目,明确指定该路由的源地址为VIP。
也就是说,客户端请求发送到LB上,源和目标IP为CIP:VIP,LB上有VIP和DIP,重新改写MAC地址后通过DIP发送给某个realserver,如RS1,此时源和目标IP还是CIP:VIP,但是目标MAC地址改写为RIP1所在网卡的MAC地址"RS1_MAC",RS1发现自身有VIP地址,所以收下此数据报文(所以在RS上必须配置VIP)。返回时,RS1根据路由表直接返回给客户端,此时,源和目标IP是VIP:CIP。
采用VS/DR模式时的基本属性和要求:
- RealServer的RIP和director的DIP必须处于同一网段中,以便使用MAC地址进行通信。
- realserver上必须配置VIP地址,以便接收director转发过来的数据包,以及作为响应报文的源IP。
- realsever响应给客户端的数据包的源和目标IP为VIP-->CIP。
- 需要添加一条特殊的路由条目,使得后端服务器返回响应给客户端时的源IP为VIP。
- director只处理入站请求,响应请求由realserver完成。
(4).lvs-ipvs的三种模式比较
三种模式的比较如图所示:
在性能上,VS/DR和VS/TUN远高于VS/NAT,因为调度器只处于从客户到服务器的半连接中,按照半连接的TCP有限状态机进行状态迁移,极大程度上减轻了调度器的压力。VS/DR性能又稍高于VS/TUN,因为少了隧道的开销。但是,VS/DR和VS/TUN的主要区别是VS/TUN可以跨网络实现后端服务器负载均衡(也可以局域网内),而VS/DR只能和director在局域网内进行负载均衡。
3.VS/TUN和VS/DR模式中的ARP问题
在【【VS/TUN和VS/DR的arp问题】】中非常详细地分析了ARP、arp_ignore和arp_announce相关原理和设置方法。此处简单说明为何需要设置arp抑制以及设置arp抑制的方法。
当一个目标IP地址为VIP的数据包进入Director前端的路由器时,路由器会向局域网内发送ARP广播,以找出VIP地址的MAC地址在哪台主机上。
Director和各RS都配置了VIP。当路由器发送ARP广播后,Director和RS都会收到这个广播包,且都认为这个广播包找的就是自己,于是都回应给路由器,这样路由器上的ARP缓存表中的条目VIP<-->vip_MAC
就不断被覆盖直到最后一个回应。这样一来,路由器将把客户端的数据包发送给最后一个回应的主机,这台主机的VIP可能是Director上的,也可能是某个RS上的。在一定时间内,路由器收到目标IP为VIP的数据包都会发送给该主机。但路由器会定时发送ARP广播包,这样一来ARP缓存表中的VIP对应的MAC地址可能会换成另一台主机。
因此,必须要保证路由器只保存Director上VIP对应的MAC地址,即只允许Director才对路由器的ARP广播进行回应。也就是说,所有RS上的VIP必须隐藏起来。
一般通过将Real Server上的VIP设置在lo接口的别名接口上(如lo:0),并设置arp_ignore=1
和arp_announce=2
的方式来隐藏RS上的VIP。至于VIP为何要设置在lo接口上以及为何要这样设置这两个arp参数,请参看【【VS/TUN和VS/DR的arp问题】】,内容非常详细。
echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
或者
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
或者将arp参数设置到内核参数配置文件中以让其永久生效。
echo "net.ipv4.conf.all.arp_ignore=1" >>/etc/sysctl.conf
echo "net.ipv4.conf.all.arp_announce=2" >>/etc/sysctl.conf
sysctl -p
在网上几乎所有文章还设置了lo接口上的arp参数:
echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce
但这没有任何意义,因为从lo接口不受arp参数的影响。
应该在配置VIP之前就设置arp参数,以防止配置VIP后、设置arp抑制之前被外界主机发现。
4.LVS负载均衡的调度算法
LVS的调度算法,详细内容见官方手册:http://www.linuxvirtualserver.org/zh/lvs4.html。
IPVS在内核中的负载均衡调度是以连接为粒度的。在HTTP协议(非持久)中,每次从WEB服务器上获取资源都需要建立一个TCP连接,同一用户的不同请求会被调度到不同的服务器上,所以这种细粒度的调度在一定程度上可以避免单个用户访问的突发性引起服务器间的负载不平衡。
LVS分为两种调度方式:静态调度和动态反馈调度。
静态调度方式是指不管RS的繁忙程度,根据调度算法计算后轮到谁就调度谁。例如两台realserver,一开始双方都在处理500个连接,下一个请求到来前,server1只断开了10个,而server2断开了490个,但是此时轮到了server1,就会调度server1而不管繁忙的程度。
动态调度方式是指根据RS的繁忙程度反馈,计算出下一个连接应该调度谁(动态反馈负载均衡算法考虑服务器的实时负载和响应情况,不断调整服务器间处理请求的比例,来避免有些服务器超载时依然收到大量请求,从而提高整个系统的吞吐率)。
在内核中的连接调度算法上,IPVS已实现了以下八种调度算法:默认的算法为wlc。
- 静态调度:
- 轮叫调度(Round-Robin Scheduling,rr)
- 加权轮叫调度(Weighted Round-Robin Scheduling,wrr),按照权重比例作为轮询标准
- 目标地址散列调度(Destination Hashing Scheduling,dh),目标地址哈希,对于同一目标IP的请求总是发往同一服务器
- 源地址散列调度(Source Hashing Scheduling,sh),源地址哈希,在一定时间内,只要是来自同一个客户端的请求,就发送至同一个realserver
- 动态反馈调度:
- 最小连接调度(Least-Connection Scheduling,lc),调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某服务器,其连接数加1;当连接中止或超时,其连接数减1。当各个服务器的处理能力不同时,该算法不理想。
- 加权最小连接调度(Weighted Least-Connection Scheduling,wlc)
- 基于本地的最少连接(Locality-Based Least Connections Scheduling,lblc),目前该算法主要用于cache集群系统。
- 带复制的基于局部性最少连接(Locality-Based Least Connections with Replication Scheduling,lblcr),目前主要用于Cache集群系统。
回到Linux系列文章大纲:http://www.cnblogs.com/f-ck-need-u/p/7048359.html
回到网站架构系列文章大纲:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
回到数据库系列文章大纲:http://www.cnblogs.com/f-ck-need-u/p/7586194.html
转载请注明出处:http://www.cnblogs.com/f-ck-need-u/p/8451982.html
注:若您觉得这篇文章还不错请点击右下角推荐,您的支持能激发作者更大的写作热情,非常感谢!
原文地址:https://www.cnblogs.com/f-ck-need-u/p/8451982.html