共计 7483 个字符,预计需要花费 19 分钟才能阅读完成。
作者:vivo 互联网运维团队 - Duan Chengping
在大规模业务场景中,曾经不可能通过单机提供业务,这就衍生出了负载平衡的需要。为了满足适合牢靠的负载,本文将从简略的根底需要登程,一步步推动并解释如何建设负载平衡平台。
一、怎么保障你的业务牢靠
想一个问题:假如你有 10 台服务器对外提供雷同的服务,你如何保障这 10 台服务器能稳固解决内部申请?
这里可能有很多种 解决方案,但实质上都是解决下述两个问题:
① 客户端的申请应该调配去哪一台服务器比拟好?
② 万一其中某些服务器故障了,如何隔离掉故障服务器?
问题① 解决不好,可能会导致 10 台服务器中的一部分服务器处于饥饿状态,没有被调配客户端申请或者是调配得很少;而另一部分则始终在解决大量的申请,导致不堪负重。
问题② 解决不好,则 CAP 准则中的可用性 (A) 可能就没法保障,除非零碎不须要 A。
要解决上述问题,你必须 实现一套控制器,能调度业务申请和治理业务服务器。很可怜的是,大多数状况下这个控制器往往就是整个零碎的瓶颈。因为控制系统如果不深刻到客户端上,就必须依赖一个集中式的决策机构,这个机构必然要承载所有客户端的申请。这时候你又得去思考这个控制器的冗余和故障隔离的问题,这就变得无休无止。
二、业务和管制隔离
那么,如何解决上述问题?
那就是业余的事件交给业余平台去做,即,咱们须要独立的负载平衡提供上述 2 点的解决方案。
对于客户端来说,每次申请一个站点,最终都会转变成对某个 IP 发动申请。所以只有能管制客户端拜访的 IP 地址,咱们就能管制申请应该落到哪个后端服务器上,从而达到调度成果,这是 DNS 在做的事件。或者,劫持客户端所有申请流量,对流量重新分配申请到后端服务器上。这个是 Nginx、LVS 等的解决形式。
图 1、通过 DNS 实现负载平衡的成果示意图
图 2、通过 LVS/Nginx 实现负载平衡的成果示意图
这两个形式都能达到负载平衡的成果。但这外面有个重大的问题,DNS、Nginx、LVS 等服务在互联网时代不可能单机就能提供业务,都是集群式(也就是有 N 台服务器组成),那这些集群的可靠性和稳定性又该如何保障呢?
DNS 次要负责域名解析,有肯定的负载平衡成果,但往往负载成果很差,不作为次要思考伎俩。Nginx 提供 7 层负载平衡,次要靠域名来做业务辨别和负载。LVS 是 4 层负载平衡,次要靠 TCP/UDP 协定、IP 地址、TCP/UDP 端口来辨别服务和负载。
为了解决 Nginx、LVS 这些负载均衡器集群的负载平衡及可靠性,咱们能够做下述简略的 计划:
- 业务服务器的负载和可靠性由 Nginx 保障;
- Nginx 的负载和可靠性由 LVS 保障。
上述计划是遵循了 业务 <– 7 层负载 <– 4 层负载 的逻辑,实际上是在网络分层模型中的 应用层 <– 传输层 的做两级负载。能够看出,其实这个计划是用另一层负载平衡来解决以后层级的负载和可靠性的问题。但这个计划还是有问题,业务和 Nginx 集群这两层的负载和可靠性是有保障了,但 LVS 集群这一层的可靠性怎么办?
既然咱们在网络分层模型中 应用层 <– 传输层 做了两级负载,那有没有可能做到 应用层 <– 传输层 <– 网络层 的三级负载?很侥幸的是,基于 IP 路由的形式,网络设备(交换机、路由器)人造具备了网络层负载平衡性能。
到此,咱们能够实现整个负载平衡链条:业务 <– 7 层负载(Nginx) <– 4 层负载(LVS) <– 3 层负载(NetworkDevices);
从这里能够看出,要确保整个负载平衡体系是无效牢靠的,必须从网络层开始构筑。处于高层级的业务,能够为低层级的业务提供负载。绝对于低层级,高层级的业务都能够认为是低层级业务的管制面,能够交给业余团队去实现和治理,低层级业务侧只须要关注业务自身实现即可。
图 3、网络 7 层模型和 LVS、Nginx 之间的对应关系
网络 7 层分层模型阐明:
7、应用层: 反对网络应用,利用协定仅仅是网络应用的一个组成部分,运行在不同主机上的过程则应用应用层协定进行通信。次要的协定有:HTTP、FTP、Telnet、SMTP、POP3 等。
6、表示层: 数据的示意、平安、压缩。(理论使用中该层曾经合并到了应用层)
5、会话层: 建设、治理、终止会话。(理论使用中该层曾经合并到了应用层)
4、传输层: 负责为信源和信宿提供应用程序过程间的数据传输服务,这一层上次要定义了两个传输协定,传输控制协议即 TCP 和用户数据报协定 UDP。
3、网络层: 负责将数据报独立地从信源发送到信宿,次要解决路由抉择、拥塞管制和网络互联等问题。
2、数据链路层: 负责将 IP 数据报封装成适合在物理网络上传输的帧格局并传输,或将从物理网络接管到的帧解封,取出 IP 数据报交给网络层。
1、物理层: 负责将比特流在结点间传输,即负责物理传输。该层的协定既与链路无关也与传输介质无关。
三、如何实现 4 层负载平衡
下面说过, 3 层负载 由网络设备人造提供,但理论应用中是和 4 层负载紧耦合的,个别不独立提供服务。 4 层负载 能够间接为业务层提供服务,而不依赖 7 层负载(7 层负载次要面向 HTTP/HTTPS 等业务),所以咱们这里次要针对 4 层负载 来讲。
3.1 如何转发流量
实现负载平衡,话中有话就是实现流量重定向,那么,首要解决的问题是如何转发流量。
4 个问题要解决:
① 如何把客户端的流量吸引到负载均衡器上?
② 负载均衡器如何抉择适合的后端服务器?
③ 负载均衡器如何将申请数据发送到后端服务器上?
④ 后端服务器如何响应申请数据?
对于①,
解决方案很简略,给一批后端服务器提供一个独立的 IP 地址,咱们称之为 Virtual IP(也即 VIP)。所有客户端不必间接拜访后端 IP 地址,转而拜访 VIP。对于客户端来说,相当于屏蔽了后端的状况。
对于②,
思考到处于低层级的负载平衡通用性,个别不做简单的负载策略,相似 RR(轮询)、WRR(带权重轮询)的计划更适合,能够满足绝大多数场景要求。
对于③,
这里的抉择会往往会影响这④的抉择。现实状况下,咱们冀望是客户端的申请数据应该一成不变的发送到后端,这样能防止数据包被批改。后面提到的网络七层分层模型中,数据链路层的转发能够做到不影响更下层的数据包内容,所以能够满足不批改客户端申请数据的状况下转发。这就是网络常说的二层转发(数据链路层,处在七层网络模型中的第二层),依附的是网卡的 MAC 地址寻址来转发数据。
那么,假如把客户端的申请数据包当成一份利用数据打包送到后端服务器是不是可行?该形式相当于负载均衡器和后端建设了一个隧道,在隧道两头传输客户端的申请数据,所以也能够满足需要。
上述两种解决方案中,依赖数据链路层转发的计划称之为 间接路由形式(Direct Route),即 DR 模式;另一种须要隧道的计划称之为 隧道(Tunnel)模式。DR 模式有一个毛病,因为依赖 MAC 地址转发,后端服务器和负载均衡器必须在同一个子网中(能够不谨严认为是同一个网段内),这就导致了只有和负载平衡服务器在同子网的服务器能接入,不在同一个子网的这部分就没有应用负载平衡的机会了,这显然不可能满足以后大规模的业务。Tunnel 模式也有毛病:既然数据转发依赖隧道,那就必须在后端服务器和负载均衡器之间建设隧道。如何确保不同业务人员能正确在服务器上配置隧道,并且能监控隧道失常运行,难度都很大,须要一套实现的治理平台,话中有话即治理老本过高。
图 4、DR 模式的转发示意图,响应流量不会通过负载均衡器
图 5、Tunnel 模式转发示意图,和 DR 一样,响应流量不会通过负载均衡器
既然都不是很现实,那还有没有其余计划?
咱们冀望的是后端服务器不感知前端有负载平衡存在,服务能够放在任何中央,且不做任何过多配置。既然做不到一成不变传送客户端的数据包,那就代理客户端的申请。也就是对客户端收回来的数据包的源 IP 和目标 IP 别离做一次 IP 地址转换。
具体来说,负载均衡器收到客户端 A 的申请后,本人以客户端的角色向后端服务器发动雷同的申请,申请所带的 payload 来自于客户端 A 的申请 payload,这样保障了申请数据统一。
此时,负载均衡器相当于发动了一个新连贯(不同于客户端 A 发动的连贯),新建的连贯将会应用负载均衡器的 IP 地址(称之为 LocalIP)作为源地址间接和后端服务器 IP 通信。
当后端返回数据给负载均衡器时,再用客户端 A 的连贯将数据返回给客户端 A。整个过程波及了两个连贯,对应两次 IP 地址转换,
- 申请时刻:CIP→VIP, 转换成了 LocalIP→后端服务器 IP,
- 数据返回时刻:后端服务器 IP→ LocalIP, 转换成了 VIP→ CIP。
客户端该过程齐全基于 IP 地址转发数据,而不是 MAC 地址,只有网络可达,数据就能够顺畅在客户端和后端之间传输。
图 6、FULLNAT 转发模式
上述计划称之为FULLNAT 转发模式,也就是实现了两次地址转换。显然,这种形式足够简略,不须要后端服务器做任何调整,也不限度后端部署在何处。但也有个显著问题,那就是后端看到的申请全副来自于负载均衡器,实在的客户端 IP 信息齐全看不到了,这就相当于屏蔽了实在客户端的状况。侥幸的是数据中心中绝大多数利用并不需要明确晓得实在客户端的 IP 地址信息,即使是须要实在客户端 IP 信息,负载均衡器也能够将这部分信息加载在 TCP/UDP 协定数据中,通过按需装置肯定的插件获取。
综合上述几种计划来说,FULLNAT 模式 对咱们的业务场景(非虚拟化环境)适宜度是最佳的。
既然咱们打算应用FULLNAT 模式,则④的解决就没有任何艰难了,因为负载均衡器间接充当了客户端角色,后端的数据必然要全副转发给负载均衡器,由负载均衡器再发给真正的客户端即可。
表 1:各种模式之间的优劣势剖析
3.2 如何剔除异样后端服务器
负载平衡个别提供对后端的健康检查探测机制,以便能疾速剔除异样的后端 IP 地址。现实状况下,基于语义的探测是最好的,能更无效的检测到后端是不是异样。但这种形式一来会带来大量的资源耗费,特地是后端宏大的状况下;这还不是特地重大的,最重大的是后端可能运行了 HTTP、DNS、Mysql、Redis 等等很多种协定,治理配置十分多样化,太简单。两个问题点加起来导致健康检查太过于轻便,会大量占用原本用于转发数据的资源,治理老本过高。所以一个简略无效的形式是必要的,既然作为 4 层负载,咱们都不去辨认上游业务是什么,只关注 TCP 或者 UDP 端口是不是可达即可。辨认下层业务是什么的工作交给 Nginx 这类型的 7 层负载去做。
所以只有定期检查所有后端的 TCP/UDP 端口是否凋谢,凋谢就认为后端服务是失常的,没有凋谢就认为是服务异样,后端列表中剔除,后续将不再往该异样后端转发任何数据。
那么如何探测?既然只是判断 TCP 端口是不是失常凋谢,咱们只有尝试建设一个 TCP 连贯即可,如果能建设胜利,则表明端口是失常凋谢的。然而对于 UDP 来说,因为 UDP 是无连贯的,没有新建连贯的这种说法,但同样可能靠间接发送数据来达到探测的目标。即,间接发送一份数据,假如 UDP 端口是失常凋谢的,所以后端通常不会做响应。如果端口是没有凋谢的,操作系统会返回一个 icmp port unreachable 状态,能够借此判断端口不可达。但有个问题,如果 UDP 探测数据包里带了 payload,可能会导致后端认为是业务数据导致收取到无关数据。
3.3 如何实现负载均衡器的故障隔离
后面咱们说过,4 层负载平衡依赖于网络层衡来确保 4 层负载均衡器之间的负载是均衡的,那么负载均衡器的故障隔离就是依赖于网络层来做。
具体如何做?
实际上,咱们是依赖于路由的形式来做网络层的负载平衡,负载平衡集群中每台服务器都把雷同的 VIP 地址通过路由协定 BGP 通告给网络设备(交换机或者路由器),网络设备收到雷同的一个 VIP 来自不同的服务器,就会造成一个等价路由(ECMP),话中有话就是造成负载平衡。所以如果咱们想要隔离掉某台负载均衡器的话,只有在该服务器上把通过 BGP 路由协定公布的 VIP 撤销即可,这样,上游交换机就认为该服务器曾经被隔离,从而不再转发数据到对应设施上。
图 7、通过撤销 VIP 路由进行故障隔离
至此,咱们曾经实现了一个基于 FULLNAT,次要依赖三层协定端口做健康检查,通过 BGP 和网络设备对接实现 VIP 收发的形式实现负通用载平衡架构模型。
四、VGW 的实现计划
基于上述 4 层负载的架构,咱们建设了 VGW(vivo Gateway),次要对内网和外网业务提供 4 层负载平衡服务。上面咱们将从逻辑架构、物理架构、冗余保障、如何进步管理性转发性能等方面进行阐明。
4.1 VGW 组件
VGW 外围性能是简单平衡,同时兼具健康检查,业务引流等性能,所以组成 VGW 的组件次要就是外围的负载平衡转发模块、健康检查模块、路由管制模块。
- 负载平衡转发模块:次要负责负载计算和数据转发;
- 健康检查模块:次要负责检测后端(RealServer)的可用状态,并及时革除不可用后端,或者复原可用后端;
- 路由管制模块:次要进行 VIP 公布引流和隔离异样 VGW 服务器。
4.2 逻辑架构计划
为了不便了解,咱们把 客户端到 VGW环节的局部称之为内部网络 (External),VGW 到后端(RealServer) 之间的环节较外部网络(Internal)。从逻辑架构上将,VGW 性能很简略,就是把 External 的业务申请平均散发到 Internal 的 RealServer 上。
图 8、VGW 逻辑示意图
4.3 物理架构计划
物理架构上,对于提供内网的 VGW 和外网的 VGW 会有肯定差别。
外网 VGW 集群应用了至多 2 张网卡,别离接外网侧网络设备和内网侧网络设备。对于 VGW 服务器来说,两个网口延长出两条链路,相似人的一双手臂,所以称这种模式为 双臂模式,一个数据包只通过 VGW 服务器的单张网卡一次。
图 9、外网 VGW 物理示意图
而内网 VGW 和外网不同,内网 VGW 则只用应用了 1 张网卡,间接内网侧网络设备。绝对应的,该形式称为单臂模式,一个数据包须要须要先从仅有的一张网卡进,而后再从网卡出,最初转发到内部,总计穿过网卡 2 次。
图 10、内网 VGW 物理示意图
4.4 VGW 现有业务模型
后面咱们说过,负载平衡能够为 7 层负载提供更上一层的负载平衡。
- 以后 VGW 最大的业务流量来自于 7 层接入接出平台(也就是 Nginx)的流量,而 Nginx 根本承载了公司绝大部分外围业务。
- 当然 Nginx 并不能反对所有类型的业务,间接构建于 TCP、UDP 之上的非 HTTP 类型这一部分流量 7 层 Nginx 并不反对,这类业务间接有 VGW 将数据转发至业务服务器上,两头没有其余环节,比方 kafka、Mysql 等等。
- 还有一部分业务是用户自建了各种代理平台,相似于 Nginx 等等,但也由 VGW 为其提供 4 层负载平衡。
图 11、VGW 业务模型图
4.5 VGW 的冗余保障
为了进步可用性,那么思考哪些危险?大家自然而然的思考到服务器故障、过程故障等场景。但 VGW 场景须要思考更多,因为 VGW 整个零碎包含了链路、网络设备、服务器、过程等。而且还不能只思考设施宕机这种简略的场景,实际上,上述任何设施呈现不宕机但转发异样的状况才是最麻烦的。
所以监控 VGW 服务转发是不是失常是第一步,咱们通过布放在不同机房和地区的探测节点定期和 VIP 建设连贯,通过建设连贯的失败比列来作为掂量 VGW 是不是失常的规范。实际上,该监控相当于检测了整个波及 VGW 的所有环节的链路和转发是不是良好的。
下面的监控笼罩到的是集群级别的探测,当然咱们也建设了其余更细粒度的监控来发现具体问题点。
在有监控一手数据之后,咱们就能提供服务器级别故障解决和集群级别的故障解决能力。
- 所有设施级别的间接宕机,VGW 做到主动隔离;
- 所有链路级别的异样,一部分能主动隔离;
- 所有过程级别的异样,能达到主动隔离;
- 其余非齐全故障的异样,人工染指隔离。
服务器级别故障隔离 是将某一些 VGW 服务器通过路由调整将勾销 VIP 的公布,从而达到隔离目标;
集群级别故障隔离是将整个 VGW 集群的 VIP 勾销公布,让流量主动被备用集群牵引,由备用集群接管所有业务流量。
图 12、服务器、链路级别故障隔离
图 13、集群级别的故障隔离
4.6 如何进步 VGW 性能
随着业务量级越来越大,VGW 单机要接管近百万的 QPS 申请,同时要达到 500W/ s 以上的包解决能力。显然个别服务器根本无法达到这么大量的申请和包处理速度,次要起因在于 Linux 的网络解决机制。网络数据包都必须通过 Linux 内核,网卡收到数据包后都要发送中断给 CPU,由 CPU 在内核解决,而后再拷贝一份正本给应用程序。发送数据也要通过内核进行解决一遍。频繁的中断、用户空间和内核空间之间一直的拷贝数据,导致 CPU 时长重大被耗费在了网络数据处理上,包速率越大,性能越差。当然还有其余诸如 Cache Miss,跨 CPU 的数据拷贝耗费等等问题。
这里会很容易想到,能不能把下面 CPU 干的这些脏活累活扔网卡去干了,CPU 就纯正解决业务数据就行。目前很多计划就是依据这个想法来的,硬件计划有智能网卡,纯软件计划以后用的较多的是 DPDK(Intel Data Plane Development Kit)。显然智能网卡的老本会偏高,而且还在倒退阶段,利用有肯定老本。而 DPDK 纯软件来说在老本和可控方面要好得多,咱们抉择了 DPDK 作为底层的包转发组件(实际上是基于爱奇艺开源的 DPVS 的二次开发)。
DPDK 次要是拦挡了内核的包解决流程,将用户数据包间接上送至应用程序中,而不是由内核进行解决。同时摈弃了依附网卡中断的形式解决数据的行为,转而采纳轮询的形式从网卡中读取数据,从达到升高 CPU 中断的目标。当然还利用了 CPU 亲和性,应用固定的 CPU 解决网卡数据,缩小过程的切换耗费。另外还有很多对于 Cache、内存等方面的优化技术。总体上可能将服务器网卡包处理速度达到千万 PPS,极大晋升网卡的包解决能力,进而能晋升服务器的 CPS(每秒新建连贯数目)。以后咱们在 100G 网卡下,可能达到 100w+ 的 CPS 和 1200w+PPS 的业务处理量(无限条件下的测试后果,非理论值)。
图 14、VGW 应用的底层工具 DPVS(DPDK+LVS)比照几种现有的负载平衡计划性能
五、总结
通过上述解说,咱们逐渐从一个业务可靠性的需要推演出一套可行的负载平衡计划,同时联合 vivo 的理论需要,落地了咱们的 VGW 负载平衡接入平台。当然,以后的负载平衡计划都是大量取舍后的后果,不可能做到完满。同时咱们将来还面临着新的业务协定反对的问题,以及数据中心去中心化的业务模型对负载平衡的集中式管制之间抵触的问题。但技术始终在提高,但总会找到适合的计划的!