Hi~各位读者朋友们,感谢您阅读本文,我是笠泱,本期分享LVS(Linux Virtual Server)这项大名鼎鼎的负载均衡技术,对其原理和应用做简要分析,以及对高可用的一些探讨,最后对比了常见几款负载均衡产品。
本期导语
什么是负载均衡?
负载均衡(Load Balance)是为企业需求提供的可解决容量问题的有效方案,使客户端的网络流量或应用程序处理负载可以在计算机集群中让每个服务端节点尽可能平均地分摊处理,实现处理负载在服务端节点之间的动态分配。
负载均衡按OSI网络层次的技术类型可以分为:
- 基于4层的负载均衡技术,根据ip+port接收请求再转发到相应的后端服务器,常见的产品如LVS(Linux Virtual Server)
- 基于7层的负载均衡技术,根据URL、主机名、浏览器类别等来决定如何进行负载均衡,常见的产品如Nginx、HAProxy
按采用的设备对象实现方式可以分为:
- 硬件负载均衡设备,如F5、深信服、Radware
- 软件负载均衡产品,如LVS、HAProxy、Nginx、Ats(apache traffic server)
为什么需要负载均衡?
咱们先看一个问题场景:某一小型的ISP企业,主要为附近不同小区居民提供上网服务,因每个居民小区上网特点不一,导致各个小区每条带宽线路在不同时段的带宽资源利用率不平衡,高峰期用户上网体验不佳。
上述场景已将问题描述清晰,即如何将三个小区的上网流量能均匀的分摊在三个10M的带宽接入服务器上,把ISP企业30M带宽资源发挥最大功效。按照架构演化设计常用思路“没有什么是加入一层中间层解决不了的,如果不能那就再加一层”,我们很容易想到需要引入一个“中间层”来负责汇聚三个小区的上网流量,然后把流量均匀负载到三个带宽接入服务器上,按这样的思路,架构会演化成:
针对上述引入的这类“中间层”一般称之为负载均衡调度器,为最终解决ISP企业的难题,还有一些细节需要讨论,这个负载均衡器需尽量满足如下要求:
1、处理网络流量的速度得特别快,不能成为新的瓶颈;
2、若能对数据包不拆包,不触碰应用层数据,工作在OSI的四层,只观察传输层包数据,能极大提升性能;
3、为进一步提升性能,要求不和客户端进行TCP三次握手,也不建立socket连接,仅负责按一定规对流量转发;
4、负载均衡器做为中间层对客户端和服务端而言无感知,相当于客户端和服务端直接通信;
5、后端服务器部署应是镜像的,不管负载到哪台后端服务器都能正常一致地响应用户请求;
LVS
LVS简介
详细参阅LVS官网:http://www.linuxvirtualserver.org
通过前文导语铺垫,为了引出本期内容的“主角”LVS(Linux Virtual Server),它是业内大名鼎鼎、应用十分广泛的一项负载均衡技术,是一个由国内章文嵩博士在1998年5月发起的开源软件项目,进行Linux服务器集群的开发工作,同时,Linux Virtual Server项目也是国内最早出现的开源软件项目之一,因LVS应用实在广泛,从 Linux 2.4.24版本以后已经成为Linux官方标准内核的一部分。
通过LVS提供的负载均衡技术和Linux操作系统实现了一个高性能、高可用的服务器集群,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability),从而以低廉的成本实现最优的服务性能。
LVS优势与不足
优势
- 高并发连接:LVS基于内核网络层面工作,有超强的承载能力和并发处理能力。单台LVS负载均衡器可支持上万并发连接。
- 稳定性强:因工作在网络4层之上仅作分发流量,不会和客户端进行TCP三次握手和建立socket连接,这个特点也决定了它在负载均衡软件里的性能最强,稳定性最好,对内存和CPU资源消耗极低。
- 成本低廉:硬件负载均衡器价格少则十几万,多则几十上百万,LVS只需一台通用x86服务器就能免费部署使用,性价比极高。
- 配置简单:LVS配置仅需几行命令即可完成配置,也可以写成脚本进行管理。
- 支持多种调度算法:已实现了以下八种调度算法,可根据业务场景灵活调配进行使用
- 轮叫调度(Round-Robin Scheduling)
- 加权轮叫调度(Weighted Round-Robin Scheduling)
- 最小连接调度(Least-Connection Scheduling)
- 加权最小连接调度(Weighted Least-Connection Scheduling)
- 基于局部性的最少链接(Locality-Based Least Connections Scheduling)
- 带复制的基于局部性最少链接(Locality-Based Least Connections with Replication Scheduling)
- 目标地址散列调度(Destination Hashing Scheduling)
- 源地址散列调度(Source Hashing Scheduling)
- 支持多种工作模式:支持D-NAT、full-NAT、DR、IP隧道四种工作模式,可根据业务场景,使用不同的工作模式来解决生产环境请求处理问题。
- 应用范围广:因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、DNS、ftp服务器等等
不足
对于一款4层负载均衡软件而言,已经是几乎完美的解决方案,非要说点不足之处的话,正因为LVS工作在4层,不支持7层规则修改,其次对于小规模应用不足以完全发挥出其性能优势。
LVS核心组件和专业术语
先引述LVS官网原文:“目前,LVS项目已提供了一个实现可伸缩网络服务的Linux Virtual Server框架,如下图所示。在LVS框架中,提供了含有三种IP负载均衡技术的IP虚拟服务器软件IPVS、基于内容请求分发的内核Layer-7交换机KTCPVS(还不成熟)和集群管理软件。可以利用LVS框架实现高可伸缩的、高可用的Web、Cache、Mail和Media等网络服务;在此基础上,可以开发支持庞大用户数的、高可伸缩的、高可用的电子商务应用。”
核心组件
LVS的管理工具ipvsadm和内核模块IPVS
ipvsadm:用户空间的命令行工具,用于管理集群服务;
IPVS:运行在Linux内核上的模块,可根据用户定义的集群实现请求转发;
专业术语
VS:Virtual Server #虚拟服务
DR:Director,Balancer #负载均衡器、分发器
RS:Real Sever #后端请求处理服务器
CIP:Client IP #客户端IP
VIP:Director Virtual IP #负载均衡器的虚拟IP
DIP:Director IP #负载均衡器IP
RIP:Real Sever IP #后端请求处理服务真实IP
LVS负载均衡四种工作模式
D-NAT模式
通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器的响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。该模式下进站和出站的数据流量都会经过LVS,LVS只做DNAT。
full-NAT双向转换模式
通过修改请求报文的源地址为DIP,目标为RIP来实现转发,对于响应报文而言,修改源地址为VIP,目标地址为CIP来实现转发。该模式下进站和出站的数据流量都会经过LVS,LVS做SNAT和DNAT。
值得一提的是,LVS原生模式并不支持full-NAT,需要自己手动编译内核和打上ipvs补丁包Lvs-fullnat-synproxy,该模式是章文嵩博士曾在阿里巴巴任职期间拓展开发的,以满足用户在云上使用负载均衡产品的需求,阿里云的四层SLB产品其底层技术实现就是LVS。
IP隧道模式
采用NAT技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。为了解决这个问题,调度器把请求报文通过IP隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务应答比请求报文大许多,采用IP隧道技术后,集群系统的最大吞吐量可以提高10倍。该模式下只有进站的数据流量经过LVS。
DR直接路由模式
DR(Direct Routing)直接路由通过改写请求报文的MAC地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同IP隧道技术一样,DR直接路由技术可极大地 提高集群系统的伸缩性。这种方法没有IP隧道的开销,对集群中的真实服务器也没有必须支持IP隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连在同一物理网段上。该模式下只有进站的数据流量经过LVS。
总结:
1、D-NAT和full-NAT模式请求和响应报文都经由LVS;
2、DR和IP隧道模式请求报文要经由LVS,但响应报文由RealServer直接发往Client;
3、D-NAT模式下DIP与RIP需要在同一Vlan中,RIP的网关要指向DIP,以确保响应报文经过LVS;
4、full-NAT模式下,RIP和DIP可以不在同一Vlan,但要能通信;
5、DR模式下DIP与RIP需要再同一Vlan中,但RIP的网关不能指向DIP,以确保响应报文不会经LVS,通过封装RS的MAC首部实现二层网络的数据包转发;
6、IP隧道模式下RIP和DIP可以不处于同一物理网络中,通过在原IP报文外封装新IP头实现转发,可支持远距离公网通信(需要保证RIP为合法的公网IP);
7、NAT模式下,不管是D-NAT还是full-NAT的扩展性有限,当RS节点数量过多时,负载均衡器将成为整个系统的瓶颈,因为所有的请求包合响应包都会交汇在LVS,处理速度会受到一定影响。
隐藏VIP的方法
前文提到的IP隧道模式和DR模式下Director和Real Sever都会绑定相同VIP,并且DR模式必须要求Director与Real Sever都有一块网卡连在同一物理网段上,在同一物理网段内拥有相同VIP都会响应局域网内的ARP广播,这会造成IP地址冲突,数据包无法正确路由,所以需要实现对外隐藏Real Sever的VIP,让客户端请求数据包只先到达Director的VIP;对Real Sever而言知晓自己拥有VIP,可处理目标IP为VIP的数据包。
想要实现这一目的,需要先了解几个内核参数(kernel parameter),在Linux系统中一切皆文件或文件描述符,控制arp行为的内核参数位于/proc/sys/net/ipv4/conf/*IF*/目录下
arp_ignore:定义接收到ARP请求时的响应级别,默认0 0:只要本地配置有相应的IP地址,不管在哪张网卡哪个接口上,就给予响应; 1:仅在请求的目标MAC地址配置请求到达的接口上的时候,才给予响应,这将忽略arp广播,因为arp广播携带的目标mac地址全为F。 arp_announce:定义将自己地址向外通告时的通告级别,默认0 0:将本地任何接口上的任何地址向外通告; 1:试图仅向目标网络通告与其网络匹配的地址; 2:仅向与本地接口上地址匹配的网络进行通告;
上面的解释理解起来稍微有点绕,直接看具体配置:
#以DR模式配置为例 ##在Director做如下配置 ifconfig eth0:1 192.168.1.100/24 #192.168.1.100假设为VIP,eth0:后的数字代表子接口,可以任意指定一个数字 ##在Real Sever做如下配置 ###1)修改内核 不能使用vi vim编辑 echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce ###2)设置隐藏的VIP ifconfig lo:2 192.168.1.100 netmask 255.255.255.255 #特别注意配置本地环回接口时子网掩码必须是32个1,不然服务器网络通信会出问题
总之,因为四层以下都由Linux内核控制实现,所以IP隧道模式和DR模式需要修改一些内核参数才能实现。
LVS高可用实现
实现LVS高可用最常用的做法是借助keepalived,keepalived利用虚拟路由冗余协议(Virtual Router Redundancy Protocol,简称VRRP)实现主备高可用。
这里有个容易误解的点需要特别说明下:对后端Real Server的健康检查LVS本身并不支持,而是由keepalived实现,通过用户定义的配置做健康检查,根据检查结果自动修改IPVS规则,剔除不健康的Real Server。
keepalived的诞生最初是为LVS ipvs提供高可用性,后来发展一个多功能、通用的轻量级高可用组件,可以为ipvs、Nginx、HAProxy等诸多服务提供高可用功能,主要应用在负载均衡调度器上,同时也可以检查后端各Real Server的健康状态。
但keepalived也不是万无一失的高可用解决方案,在某些特定情况下会存在“脑裂”问题。
情况一:Keepalived的BACKUP主机在收到不MASTER主机报文后就会切换成为master,如果是它们之间的通信线路出现问题,无法接收到彼此的组播通知,但是两个节点实际都处于正常工作状态,这时两个节点均为master强行绑定VIP,会出现IP地址冲突问题。
情况二:MASTER主机和BACKUP主机之间的通信线路没有问题,如果MASTER主机上的keepalived程序异常退出(比如kill -9),keepalived还来不及解除本机的VIP绑定,BACKUP又晋升为MASTER,导致两个节点的网络接口均有绑定VIP,也会出现IP地址冲突问题。
上述现象若引申下我们会发现在高可用架构设计中常会面临这样的问题:为了解决一个系统单点故障问题,会引入第三方中间件来实现高可用方案,然而第三方中间件本身的可用性又该如何保证?如果一直按照再引入一层中间层的思路往往会陷入套娃循环,我们需要知道的是软件工程领域有句箴言:“没有银弹!即没有简单方法可以解决复杂的软件系统工程问题”,世上也绝对没有一个软件系统会宣称其可用性达到了100%,只能无限逼近。
那有什么更好的办法实现LVS的高可用?答案是有的,比如可以使用投票机制算法(协议)来保证产品本身的可用行,开源解决方案比如采用zookeeper来进行选主,zookeeper本身的可用性是由ZAB(zookeeper Atomic Broadcast)一致性协议保证。值得一提的是zookeeper也是一款非常优秀的软件,其架构也十分精妙,等后续篇章笔者再来详细分享。
常见的负载均衡器的区别
指标项 |
四层负载均衡 |
七层负载均衡 |
基于 |
基于IP+Port |
基于URL、IP、主机名、浏览器类别等 |
类似于 |
路由器 |
代理服务器 |
复杂度 |
低 |
高 |
性能 |
高;无需解析数据包内容 |
中;需要算法识别host、URL、Cookie和Http head等信息 |
安全性 |
低 |
高 |
额外功能 |
无 |
会话保持,图片压缩等 |
总结:从上面的对比看来4层负载和7层负载最大的区别就是效率与功能的区别。4层负载架构设计比较简单,无需解析具体的消息内容,在网络吞吐量及处理能力上会相对比较高,而7层负载均衡的优势则体现在功能多,控制灵活强大。在具体业务架构设计时,使用7层负载或者4层负载还得根据具体情况综合考虑。
常见的负载均衡产品 |
硬件/软件 |
是否支持4层 |
是否支持7层 |
特点 |
F5 |
硬件级 |
是 |
否 |
性能最强,但成本很高 |
LVS |
软件级 |
是 |
否 |
性能强,属于重量级的四层负载软件 |
HAProxy |
软件级 |
是 |
是 |
支持会话保持,标记,路径转移、健康检查、流量调度控制等功能,性能优秀,和Nginx一样采用事件驱动的连接处理模式和单进程处理模式。 |
Nginx |
软件级 |
是 |
是 |
轻量级的负载软件,带缓存功能,正则表达式较灵活;在http协议和mail协议上功能支持较好,性能与HAProxy差不多。 |
总结:Nginx的负载均衡本质上是基于反向代理的负载均衡,不管是基于stream模块的4层还是htpp模块的7层负载均衡都需要与客户端进行TCP三次握手、建立socket连接,因为Nginx处在应用层,工作在用户态,这注定了Nginx的负载均衡性能有一定瓶颈(官方标称单台最大支持5W客户端的连接),相比之下性能不及LVS。这也是为什么企业生产环境中负载均衡组网模式一般都会选择在前级部署LVS集群以扛住流量,LVS后再部署Nginx集群以hold住连接。
本期结语
在现代网络架构中,高效的负载均衡是确保应用程序性能、可用性和安全性的重要组件。LVS、HAProxy 和 Nginx 是目前最流行的三个开源解决方案,它们在功能、性能和使用场景上各有侧重,本期内容主要介绍了LVS工作原理和应用,简单对比了其他两款负载均衡产品HAProxy 和 Nginx,以帮助读者选择适合其特定需求的解决方案。
最后,感谢您的阅读!系列文章会同步更新在微信公众号@云上的喵酱、阿里云开发者社区@云上的喵酱、CSDN@笠泱,您的点赞+关注+转发是我后续更新的动力!