当前位置: 首页 > 科技观察

20张图让你彻底掌握负载均衡的秘密!

时间:2023-03-14 08:16:40 科技观察

前言今天我们将深度解密负载均衡器LVS的秘密。相信看完这篇《你管这破玩意儿叫负载均衡?》的你,还是有很多疑问的。比如LVS,好像只有类似路由器的转发功能。为什么说它是一个四层(传输层)的负载均衡器。今天我们就来逐步揭开LVS的迷雾。本文将以图形化的方式讨论LVS的工作机制。大家最好对网络是如何连接的以及数据包的发送和接收机制有所了解,这样就会很容易理解本文的知识点。如何连接都给你安排的很清楚。没看过也没关系,本文会铺垫一些必要的知识点,让大家看得懂。负载均衡器的诞生。一直以来,小张所在公司的DAU(DailyActiveActivity)都不超过10,所以他只部署了一台机器。毕竟机器多了成本就高了,就算出了故障也不影响少数用户。但不经意间,小张的生意踩到了风口,业务量暴涨。dau达到数万,即将突破10万。小张慌了,赶紧升级了这台机器的内存、CPU等配置。结束了,但是小张明白单台机器的性能无论提升多少,都会遇到瓶颈,于是小张想了个办法,多部署几台机器,把流量平均分配到这些机器上。如何分配?最简单的方法当然是使用DNS负载均衡,在域名解析服务器上设置负载均衡策略,让流量随机命中其中一台机器。但是这个方案有以下两个明显的问题:占用太多公网IP,要知道现在租一个公网IP要上千的DNS缓存,可能会导致致命的故障第一个问题加钱可以解决,但是第二个第二个问题不能靠加钱解决,因为众所周知DNS解析是一个迭代或递归查询,需要经过根DNS服务器->顶级DNS服务器->权威DNS服务器解析IP对应域名。可想而知这个解析是多么耗时,所以一般都有DNS缓存。DNS缓存主要包括“浏览器缓存”、“操作系统缓存”、“路由器缓存”、“ISP缓存”。每次发起域名解析请求,都会依次在上述四个缓存中查找。如果命中缓存,则直接返回域名对应的IP。比如Chrome缓存1分钟,ISP缓存可能高达1~2小时,这样问题就来了,如果一台机器宕机了,但是因为上面可能还有这个域名的IP缓存四个缓存,对于请求者是无感知的,所以只要缓存还没有过期,请求者就会继续往这台死机直接发流量,造成上线失败,当然是不能容忍的。那我该怎么办?小张突然想起计算机界的一句经典名言:“没有加一层解决不了的问题,有就再加一层。”为什么不在DNS和服务器之间多加一层,让中间层来做负载均衡的工作。想了想,小张想出了如下架构图:可以看到这个负载均衡器(以下简称LB)有如下特点:外部公网ip(以下我们简称VIP)承担所有的流量,并在内部与真实服务器(RealServer,以下简称RS)进行通信。与RS在同一个内网,LB只加载转发请求的工作,实际处理逻辑交给后台RS,RS处理后将响应包发送给LB,LB再返回给客户端,所以网络拓扑图改进如下:NAT的下一个重点是LB是如何工作的。首先我们要明白,当我们说接收到一个请求时,实际上接收到的是一个数据包,那么这个数据包长什么样子呢?源IP、目的IP、源端口、目的端口,简称TCP四元组,四元组唯一确定一条链路,在传输过程中四元组不会改变。现在LB收到这个数据包后,想要转发给后面的服务器,就需要把目的IP改成服务器的IP(假设是第二台机器,它的IP地址是192.168。0.3),那么修改后的数据包如下:RS处理后,由于这个数据包会通过LB转发给客户端,所以服务器的网关要设置为LB的内网IP(即192.168.0.1)然后数据包发出去,LB会收到所有的响应数据包。此时的数据包如下:为什么RS的响应包要经过LB?因为为了保证四元组不变,LB需要在收到数据包后将源IP改为VIP,这样客户端才能识别这是对之前请求的正确响应。画外音:客户端请求和响应报文的四元组不可更改。修改后的数据包所以总结一下LB的主要工作机制:主要修改进出数据包的IP,先修改目的IP为RS的IP,将数据包交给RS处理,然后发送数据包到网关(LB),LB再修改源IP为其出口VIP,只要四元数不变,客户端就可以正常收到对其请求的响应,为了让大家更直观的体验负载均衡在IP修改,我做了动图,相信大家看了之后会理解的更深刻。从client的角度看,它认为是和LB背后的RS通信,但实际上它只和LB通信,而LB只是起到一个虚拟服务器的作用,所以我们将其命名为LVS(LinuxVirtualServer),LVS只有修改IP地址和转发数据包的功能。由于它在数据包进出的过程中修改了IP地址,所以我们称这种模式为NAT(NetworkAddressTranslation,网络地址转换)模式。可以看到在这种工作模式下,网络请求包和网络响应包都必须通过。LVS。看到这个问题似乎已经完美解决了,但是我们忽略了一个问题:每个网络包都有大小限制。如下图所示,在每个数据包中,每个payload(一般为应用层数据)的大小一般不能超过1460字节。也就是说,如果客户端的请求数据(比如HTTP请求太大)超过1460字节,就必须进行分包,服务端收到所有的分包后,再组装成完整的应用层数据。显然,同一个请求(即同一个四元组)的LVS分包应该转发给同一个RS,否则分包发给不同的RS会导致数据不完整。所以LVS需要根据四元组记录该包应该转发到哪个RS,所有具有相同四元组的包都转发到同一个RS。四元组的IP在IPHeader中,端口号在TCPHeader中,也就是说LVS需要去掉TCPHeader得到端口号,然后再决定是否转发给同一个RS根据四元组是否相同。一个四元组对应一个TCP连接,也就是说LVS有记录连接的功能,一个连接是传输层的一个概念。至此,相信你就明白了开头的问题:“LVS有转发包的功能,为什么叫四层负载均衡”。经过这样的DR设计,由于LVS负载均衡的作用,单机瓶颈就轻松解决了。小张的公司顺利通过了C10K(万并发连接),C20K,...问题,过了瓶颈期,但是随着并发数越来越高,小张发现了一个大问题,LVS渐渐的处理不了了,因为所有的数据包都要经过它,这就成了一个很大的瓶颈,随着RS横向扩展个数的增加,LVS迟早会挂掉。能不能LVS只负责转发请求包,而把响应包直接通过RS返回给客户端,类似如下:画外音:红色虚线是包的流转过程,可以看到responsepacketdoesnotpassthroughLVS响应包不需要经过LVS,自然释放了LVS的负载压力。我们称这种模式为DR(DirectRouter,直接路由)模式。现在,如何实施呢?这个设计有两个注意点:首先,LVS仍然需要承载所有的请求流量(接收所有的数据包),然后根据负载均衡算法转发给RS。RS经过处理后,直接将数据包转发给路由器,再转发给客户端,也就是说必须有和LVS一样的VIP(四元数不能改),而且从上面的拓扑图来看,他们也必须在同一个子网(严格来说应该是同一个vlan,因为是通过交换机通信的),也就是说LVS和RS都必须有两个IP,一个VIP,一个子网IP,那么一台host怎么会有两个IP?我们知道,要让一台电脑上网,首先要将网线插入网卡中。一张网卡其实就是对应一个IP,所以一台有两张网卡的主机就有两个IP,但是大部分人不知道的是一张网卡可以配置多个IP,一般有两种网络网卡,一种是物理网卡,一种是虚拟网卡。物理网卡:可以插入网线的网卡。如果有多个网卡,我们一般命名为eth0、eth1。..,如果一张网卡对应多个IP,以eth0为例,一般命名为eth0、eth0:0、eth0:1。..eth0:x,比如一台机器只有一张网卡,但是它对应两个IP192.168.1.2和192.168.1.3,那么它们绑定的网卡名称就是eth0和eth0:0。虚拟网卡:虚拟网卡通常称为loopback,一般命名为lo,是一种特殊的网络接口,主要用于本机各种应用程序之间的网络交互(即使拔掉网线,本机各种应用程序仍然可以通过lo进行通信),需要注意的是,虚拟网卡和物理网卡一样,也可以绑定任意IP地址。如果虚拟网卡上配置了任意IP地址,只要有物理网卡,就可以接收和处理目的IP为虚拟网卡上IP的数据包。lo默认绑定本地IP127.0.0.1。如果要绑定其他IP,对应的网卡名称一般为lo:0,lo:1。..画外音:一般包括LVS在内的服务器都是以双网卡的形式存在。首先,每个网卡的带宽是有限的。双网卡相当于带宽翻倍。其次,两块网卡还起到热备份的作用。如果一个网卡坏了,另一个可以在上面使用。了解了以上知识点后,我们可以对拓扑图进行如下改进:大家可能已经注意到,RS的VIP绑定的是lo:0虚拟网卡,而不是物理网卡。为什么会这样,主要是保证所有的请求都收到?在LVS上。1.arp_ignore=1首先我们知道LVS和RS都在同一个子网。我们需要了解子网的工作机制:子网一般称为以太网,主要使用mac地址进行通信。它位于ISO模型的第二层。一开始,内网的机器不知道对方的mac地址。他们需要使用arp机制,根据自己的IP获取对应的mac。获取到后,首先会在本地的arp表中记录这个IP对应的mac(下次直接在本地缓存中查找mac),然后将IP对应的mac附加到包头,然后数据包将被传输,交换机将找到相应的机器。所以当client请求VIP时,请求到了上图中的路由器,路由器需要转发给这个IP对应的机器,所以先发起arp请求,获取VIP对应的mac地址。那么现在问题来了,由于三台机器的IP都是同一个VIP,如果都响应arp请求,相当于一个IP对应三个mac,路由器应该使用谁的mac地址呢?解决方法很简单:既然所有的请求都经过LVS,那么只让LVS响应arp,抑制其他两个RS对VIP的arp响应。但是请求到达LVS后,LVS会将包转发给RS(假设是RS2)。同样使用arp获取RS的mac地址,但是注意从LVS发起的arp请求的目的IP已经变成了RS2的内网IP:115.205.4.217(绑定到物理网卡eth0)。综上所述,RS无法响应目的IP绑定虚拟网卡的VIP的arp请求,但是可以响应目的IP绑定物理网卡的IP的arp请求,这就是为什么RS需要将VIP绑定到虚拟网卡,而将内网IP绑定到物理网卡的真正原因是为了arp响应的需要。当然一般的服务器默认都会响应所有IP的arp响应,所以需要在RS上做额外的配置,即:net.ipv4.conf.all.arp_ignore=1net.ipv4.conf.lo.arp_ignore=1setarp_ignore=1意思意思如下:1-replyonlyifthetargetIPaddressislocaladdressconfiguredontheincominginterface就是我们上面说的,它只响应目的IP为接收网卡(也就是物理网卡)上的IP的arp请求(目的IP为虚拟网卡上VIP的arp请求将被忽略)。以上设置完成后,只有LVS会响应对VIP的arp请求(路由器收到LVS的arp响应后,会在arp缓存表中记录VIP的mac地址作为LVS的mac),这样就可以了可以保证所有的请求都会被LVS命中,然后LVS也成功的把数据包发给了RS2。RS2处理完之后,就准备从网卡发送数据包了,但是这里要注意RS2不能直接通过物理网卡eth0来发送数据包。这样会导致数据包的源IP变为eth0的IP(即115.205.4.217),从而导致四元组发生变化(不要问为什么,是协议栈的关系),所以我们需要额外配置,使数据包使用lo接口发送,如下:routeadd-host115.205.4.214devlo:0#添加路由,目标IP为VIP的数据包使用lo接口发送,这样响应报文的源IP就会是VIP,然后通过eth0发送出去,这样就保证了quad不会变。2.arp_announce=2接下来还有一个问题,RS2如何将数据包传递给它的网关(即路由器),由于它们还是在同一个子网中,所以它也是先通过arp获取到网关的mac,然后然后在以太网包头上安装网关的mac,传递给网关。但这里有一点需要注意。当通过arp获取网关的mac时,网卡会发送一个包含“源IP”、“目的IP”、“源mac”的arp广播包。通常源IP可以选择为数据包的源IP,也可以选择物理网卡上的IP,但是在DR模式下,这里的源IP只能选择物理网卡上的IP,为什么呢?我们知道目标IP是网关IP,所以网关会响应arp请求,但同时网关在收到arp响应后也会更新本地的arp表:sourceIP=>sourcemac,其中sourcemac是RS2的mac,还记得上面router的arp缓存表里保存了LVS的VIP和LVS的mac的对应关系吗?也就是说,如果从RS2发出的arp的源IP是数据包的源IP(即VIP),网关收到arp后,会更新路由表中的VIPmac地址为RS2!这样下次client请求router的时候,就直接把数据包转发给RS2了,不经过LVS!所以RS2需要发送arp获取网关mac时使用的源IP应该是物理网卡(eth0)对应的IP(即115.205.4.217),这样就避免了上述问题。和arp_ignore=1一样,这一项也需要我们手动配置:net.ipv4.conf.all.arp_announce=2net.ipv4.conf.lo.arp_announce=2arp_announce=2表示忽略IP数据包的源IP地址,并选择发送网卡上最合适的本地地址作为arp请求的源IP地址上面的部分有点乱,大家可以多看几遍理解一下,其实主要目的是为了防止路由器的ARP缓存表将VIPmac更新为RSmac。从上面的介绍可以看出DR模式比较复杂,需要在RS上做额外的配置,所以网上一般使用NAT模式FullNAT,但是问题又来了,如何解决单点问题NAT模式下的LVS,毕竟所有进出流量都走同一个LVS(因为RS只有一个网关),在RS的不断扩容下,单点LVS很可能成为巨大的隐患,并且LVS应该作为所有RS的网关,也就是说它们必须在同一个网段。部署在阿里云等公有云平台上肯定是不现实的,因为在公有云上,很可能RS分布在各个地方,这意味着需要跨VLAN通信,而NAT显然不符合要求,所以在NAT的基础上衍生出FullNAT,而FullNAT其实就是为公有云而生。在FullNATNAT模式下,LVS只是将数据包的目的IP修改为RS的IP,在FullNAT模式下,LVS也将源IP地址修改为LVS的内网IP(IP的修改主要由内核模块完成ip_vs的LVS来操作),注意上图中的LVS内网IP和RSIP可以在不同的网段,通常在公有云平台上,他们部署在内网,也就是企业的内网,使得LVS可以跨网段与RS通信,避免了LVS的单点瓶颈。多个LVS可以向RS转发请求。如图所示,部署了两个LVS。他们的内网和RS不在同一个网段,还是可以通信的。有的读者可能会注意到一个问题:LVS转发给RS的数据包的源IP(即客户端IP,client_ip)被替换为内网IP,也就是说RS收到的数据包中不包含client_ip,有时候client_ip在我们分析数据的过程中起着非常重要的作用(比如需要分析订单在不同地区client_ip的分布情况),这种情况下LVS会在收到数据包的TCPHeader中插入请求数据包。client_ip。上图是TCPHeader,client_ip放在tcpoption域,然后RS只要安装TOA模块就可以从中读取client_ip,TCP的option域也提示我们要合理设计技术方案添加一些冗余字段可以使您的程序更具可扩展性。综上所述,相信大家已经了解了LVSNAT、DR、FullNAT的工作机制。其实LVS也有TUNNEL隧道模式,只是生产中没有用到,就不介绍了。另外每个LVS一般都会做机器的双机热备,如下,备机可以通过定时发送心跳包来感知LVS主机的存活,注意虚线部分,备机也可以感知到服务器的存活,如果服务器挂了,LVS会把它去掉,保证LVS转发的流量不会打到宕机的机器。本文小章为张文松博士。1998年,领导开发了LVS项目。一开始只有三种模式:NAT、DR、TUNNEL。但随着阿里云上服务的兴起,这三种模式已经不能满足实际部署需要,于是他指示手下基于NAT进行改造,FullNAT诞生了。值得一提的是,LVS是少数华人开发的开源软件,被Linux官方认可。它已经集成到Linux内核中。可见,这个项目的价值和贡献是巨大的。本文转载自微信公众号“码海”,可通过以下二维码关注。转载本文请联系码海公众号。