上一篇文章的末尾,我们利用负载均衡器打造了一个五万 QPS 的系统,本篇文章我们就来了解一下负载均衡技术的发展历程,并一起用 SDN(软件定义网络)技术打造出一个能够扛住 200Gbps 的负载均衡集群。
1996 年,华盛顿大学的几个学生共同创建了一家生产负载均衡设备的公司,并用美国人民的老朋友——飓风的最高等级 F5 作为品牌名,以表示他们的设备可以扛住最狂暴的网络流量。彼时,互联网的规模每 100 天增长一倍,这也让 F5 在成立三年后火速上市。2001 年,F5 公司在经历了互联网泡沫后,顺利地把设备卖进了银行等大型机构,因为 F5 比微软和甲骨文都更有前瞻性:他们的 iControl 系统可以提供 API,让大型机构自己开发软件来控制通过负载均衡设备的所有流量。
早在 2001 年,软件的威力就已经开始展现。
2003 年非典暴发,电子商务,网络点餐甚至是网络新闻都迎来了爆发式的增长。2004 年,F5 上市了新一代产品:包含 TMOS 软件平台的全套硬件设备,一次性解决了网络访问、数据中心同步访问、远程办公、应用防火墙等多种需求。此后,市场上 F5 公司的产品越来越具有统治力。
2006 年以后,传统的 IP 层负载均衡技术开始向应用层发展,F5 等相关设备厂商也紧跟潮流开始推广“应用交付”的概念,开发了很多结合了负载均衡和应用网关的产品,这之后的十年,是传统负载均衡硬件厂商的最后荣光。
2019 年,F5 Networks 以 6.7 亿美金的价格收购了 Nginx,硬件厂商和软件厂商实现了一次梦幻联动,也侧面说明了我们确实已经迎来了软件定义网络的大时代。
实际上,在今天的企业网络架构中,专业的网关设备都已经消失,取而代之的是一个看起来不是网络设备的网络设备:防火墙。特别是具备应用识别能力的“下一代防火墙”(没错,就是这个中二的名字),更是将防火墙设备的价值推上了巅峰,并一次性让企业级路由器和中低端负载均衡全部退场,这又是一个软件战胜硬件的故事。
一个小八卦,下一代防火墙行业的个中翘楚 Fortinet 公司,由两名出生于北京的清华大学老师的孩子 2000 年在美国创办。
2002 年 2 月,戴尔为 PowerEdge 1650 服务器第一次配上了千兆以太网。当时,负载均衡的主流实现还是基于硬件的,或者说是基于“软硬件一体化解决方案”的。在当时,服务器 CPU 的单核性能还很低,甚至核心数都很少,网卡芯片技术也没有今天这般牛皮(相比于下面将的 NPU),所以当时想用运行在标准操作系统(Windows/Linux)内的软件来实现千兆软网关还是一个“前沿探索项目”。更不要说万兆负载均衡了:PowerEdge 1650 发布的四个月后,万兆以太网的标准“IEEE 802.3ae 10 Gb/s 光纤以太网”才首次发布,距离万兆网卡在服务器端普及更是还有十多年的光景。
鲜为人知的是,千兆以太网的光纤标准 1998 年才发布,千兆以太网的双绞线标准 1999 年才发布,而到了 2002 年,万兆以太网光纤标准就已经发布了。实际上,千兆以太网在消费端开始普及,也已经是 2010 年的事情了。
21 世纪的头十年,最优秀的超千兆解决方案是:利用二层网络的链路聚合协议,使用多个千兆口同时负载均衡,实现超千兆的速度。而且当时能做到数 G 带宽的负载均衡设备动辄上百万,价格惊人,有需求的终端客户简直就是大冤种,不过在那个移动通信基站都要完全进口的年代,哪个中国人不是大冤种呢。
这些网络硬件厂商,其实都是软件厂商,只不过他们选择将自己的软件装在这些黑色的铁盒子里面卖,这样的产品质量更稳定,更重要的是:这样更贵。相比于买一个看起来可以随意拷贝盗版又虚无缥缈的软件,人类社会落后的官僚体系也更容易接受购买昂贵的实物。具体的技术分析请往下看。
最近十年,随着云计算的兴起,从硬件设备到 IT 基础设施都发生了翻天覆地的变化,现在,硬件负载均衡已经开始逐步退场:云服务商们使用软件定义网络(SDN)技术,构建出了一个低成本高性能的新世界。
今天,一台总价 3 万元的通用 X86 服务器搭配 100G 以太网卡,使用基于 DPDK 开发的用户态应用程序在 Linux 上发小包,很容易就可以跑满 100Gbps 的网卡带宽¹。
这个 tweet 也许有些夸张,但是这就是我们当下的世界:软件正在定义网络的一切。
这是一台 F5 生产的售价百万的硬件负载均衡设备,它只用了一颗 4 核 8 线程的至强 x86 CPU,就实现了 40G 的四层负载均衡能力和 18G 的七层负载均衡(应用网关)能力。
这台设备内部有两个控制器和四个接口插槽,可以实现“全双活”,即控制流量的“CPU 内存主板”和“网络接口”都是双份,在任意一个资源意外宕机后,另一个备用资源可以无缝顶上,可以实现无丢包的硬件级高可用。同时,这台设备背后的电源适配器应该至少有四个,可以实现运行时热替换,甚至连风扇模组都是冗余的,可热替换的。
下面我们正式开始利用软件的力量,一步一步在标准 x86 服务器上面跑的标准 Linux 系统内,构建出一个和这台硬件负载均衡设备高可用性一致,且带宽可以达到 200G 的负载均衡集群。
让我们先从交换机技术开始讲起。
大家还记得上一篇文章中的负载均衡架构图吗:
这张图里就暗藏了一个交换机。
左侧,客户端和负载均衡器之间是使用公网 ip 通信的,他们俩是在全球互联网内的两台对等设备,只是数据包经过了很多个真·路由器的“路由”操作,双方才能收到对方发送的数据包。
右侧,负载均衡器和上游服务器通信的时候采用的是内网 ip:10.0.0.100
和 10.0.0.1
,他们俩是怎么通信的呢?通过交换机。
一台能够跑满千兆 NAT 的路由器,最低价格大概在 300 块,但是一个所有口都能同时跑满全双工千兆(上下行同时跑满千兆)的五口交换机,你知道多少钱吗?39 块钱,包邮。
为什么呢?因为交换机干的事情更为简单,可以用非常低端的芯片满足需求。
网关是通过关联两个五元组,再对数据进行修改而发挥作用的。交换机则更简单:只维护一个 MAC 地址在哪个网口上的 HASH 表即可,无需对数据进行任何修改。该表的 key 为 48 位长,value 是个 tinyint:4 口交换机可用 2 bit 表示,8 口交换机可用 3 bit 表示,现在知道为什么家用交换机都是 8 口的了吧。
交换机的工作模式简单表述如下:
除了不需要修改数据包之外,交换机也不需要和任何设备通信来建立和更新 MAC 表,只需要监听途径交换机的所有数据包的源 MAC 地址即可。
优点:
缺点:
当然,现在主流的商用二层交换机已经拥有了很多的三层特性,这些缺点通过各种检测技术都已经解决了。
准备工作做完了,下面我们开始搭建负载均衡集群。先从这一切的基础—— LVS 开源软件说起。
1998 年,在章文嵩博士二年级的时候,他发现 Cisco 的硬件负载均衡器要卖几万美金,觉得这玩意儿不难写,于是利用两周的课余时间创建并开源了 LVS(当时叫 IPVS)。时至今日,LVS 技术创造的商业价值已经无法计算,互联网上的绝大部分数据包,都会被 LVS 或者承袭 LVS 思想的软件处理。
2004 年,LVS(IPVS)被合并进了 kernel 2.4,从此开始,所有 Linux 都拥有了变身为负载均衡器的能力。
其实一句话就能说清:通过修改 MAC 层、IP 层、TCP 层的数据包,即实现了一部分交换机和网关的功能,指挥流量到达真正的服务器上。
LVS 有三个常用模式:
我们以最能体现 LVS 思想的 DR 模式为例,展示 LVS 的基本原理。
DR 模式下,LVS 只负责篡改数据包,不负责充当网关,所以我们还是需要一个网关在公网 ip 和私网 ip 之间进行 NAT 转换。我们依然假设客户端 ip 为 123.123.123.123,它发起了一个针对 110.242.68.3 的 80 端口的 HTTP 请求。
当网关接收到一个发送给 110.242.68.3 的数据包时,发现协议为 TCP,目标端口为 80,查询自己的 NAT 表发现内部 ip 为 10.0.0.100(VIP,即虚拟ip),内部端口为 80,于是网关向局域网发出了一个 IP 包。由于端口都是 80 不变,协议都是 TCP 不变,所以本次网络请求中,有四个数据非常关键:源 ip 地址,目的 ip 地址,源 MAC 地址,目的 MAC 地址。
在生产环境部署中,由于 LVS 集群是所有流量的入口,所以其可用性需要做到非常高,一般不会只部署在一个机房里,所以现实中最常用的是 NAT 模式:双向流量均经过 LVS 集群,这样便可以实现多地多中心的跨公网多活。
通过上面的过程,你应该能看出来 LVS 的运行原理了:它通过在 LVS 和上游服务器上配置虚拟 ip
,以对数据包进行篡改后再发送
为手段,在标准以太网模型下构建出了一个可行的负载均衡系统。它不像交换机那样完全不修改数据包,也不像网关那样维持一个对应关系并修改很多东西,它篡改了数据包,但不多,所以可以实现非常高的性能。
LVS 的数据处理组件 IPVS 运行在内核态,避免了用户态的进程切换开销,再配合低负载的 DR 模式,可以进一步提升性能。
由于有内核态加持,LVS 比 HAProxy 和 Nginx 的单机性能都要强很多。
OSPF:开放式最短路径优先协议,一种基于链路状态的内部网关协议。每个OSPF路由器都包含了整个网络的拓扑。并计算通过网络的最短路径。OSPF会通过多播的方式自动对外传播检测到的网络变化。
ECMP:等价多路径协议。即当存在多条不同的链路到达同一目的地址时,利用ECMP可以同时使用多条链路,不仅增加了传输带宽,还可以无时延、无丢包的备份失效链路的数据传输。如果利用传统的路由算法,只能利用其中的一条链路进行数据的传输。
LVS 是运行在标准以太网模型下的负载均衡软件,配合 Keepalived 可以实现高可用。而 ECMP 协议是专业的多链路路由协议,可以实现不丢包的多活,我们下面还会用到。
LVS 就是网关型负载均衡继续拆单点的结果:LVS 自己只承担数据包重定向工作,将转发留给基础网以太网来解决,在单机上实现了非常高的系统容量。在最新的服务器硬件上,单个 LVS 即便在开销更大的 NAT 模式下也可以实现大约 20G 的 TCP 带宽²。
LVS 单机 20G 的带宽显然和我们 200G 的目标还相去甚远,但是我们接下来要做的第一件事并不是提升系统容量,而是先提升系统的稳定性:搭建高可用架构。
Keepalived 是一个非常优秀的搭建高可用集群的开源软件,它最开始就是为了和 LVS 配合而出现的,主要的作用是构建一个自选举集群。它支持 3 台控制器集群独立部署,也支持部署到应用机器上。它和 LVS 一样基于虚拟 IP 技术,可以在任意标准以太网内运行。
Keepalived 运行原理说起来其实非常简单:
LVS 和 Keepalived 配合,基于多台物理机,可以实现一个高可用的负载均衡集群,架构图如下:
如果 Master 因为任何原因失效(硬件故障,机房断电,人为误操作,光缆挖断,火灾地震),Standby 机器就会迅速顶上,接管流量,实现高可用的目的。
金融级项目可以在一个城市跨三个机房做三节点的 Keepalived 集群。为什么不做多城市集群?因为多城市已经属于“两地三中心”的高可用技术领域,一般不在二层网络上做,跨城市专用光纤的建设费用是非常高的,城市内拉光纤就便宜多了。我们最后一篇文章会讲终极高可用架构。
我司办公区自建机房内也部署了一些非关键业务,其性能要求并不高,所以我选择单独部署 Keepalived:和 Kong 网关配合提供高可用网关;和 MySQL 配合做双主双活集群;和 Apache 配合做一个跨越 4 台物理机的虚拟机集群,提供高可用 HTTP 服务;等等其它案例不再赘述。
有了 Keepalived,我们就有了集群高可用的基础,下面我们开始啃硬骨头:从 20G 到 200G。
最新的 AMD EPYC 9654 服务器 CPU 有 96 个物理核心,双路平台共有 384 个 vCore,但是 LVS 单机性能依旧徘徊在 20G 附近,为何性能无法继续提升呢?因为 Linux 网络栈已经达到性能极限了。
由于 LVS 基于 Kernel 里的 Netfilter,依赖 Linux 网络栈,导致进程切换需要读写内存,数据包的发送和接收也要读写内存,在极高的带宽需求之下,相对耗时的内存读写就成了阻碍性能进一步提升的最大障碍。DPDK 和 NPU 硬件卸载就是这个问题的两个解决方案。
DPDK 是 Intel 开源的高性能网络数据处理框架,运行在用户态的进程通过申请大页内存和轮询代替中断两个关键特性,给高速率网卡提供了一个高性能解决方案。它的 CPU 亲和性、多核调度架构、内存 NUMA 优化等基础架构又进一步推高了性能,最终让它成功脱颖而出成为用户态网络界面框架的首选。
爱奇艺开源的 DPVS https://github.com/iqiyi/dpvs 就是 DPDK 技术在负载均衡领域的成功运用。在 10G 网络下发送 64 字节的小包进行测试,DPVS 可以做到标准 LVS 的五倍性能。在这里我们保守一点,对折一下 2.5 倍,那 DPVS 的单网卡性能极限就是 50G。
最新的 NPU 已经可以支持很多的硬件卸载特性:IP 分片、TCP 分段、小包重组、checksum 校验、硬件 QOS,以及最重要的 VXLAN(虚拟扩展本地局域网) 的剥离和插入:此功能是 DPVS 的重要组成部分,可以减少数据流互相干扰,大幅提升系统总容量。
此外,RDMA 技术也是网卡芯片的一大进步方向,我们将会在后面讲数据库的计算和存储分离的时候详细了解。
除了 Linux 网络栈的限制,LVS 本身架构上的全局锁也是一个突破口,全局锁导致了海量的 CPU 核心无法被利用,我们可以借鉴阿里云的处理思路:
阿里云通过 RSS 技术把同一个五源组报文扔到同一个 CPU 上处理,保证入方向的所有相同连接上的报文都能交给相同的 CPU 处理。同时在每个核在转发出去时都用当前 CPU 上的 local 地址,通过设置一些 fdir 规则,报文回来时后端服务器访问的目的地址就是对应 CPU 上的 local 地址。这样就能实现这一条连接上面左右方向的报文都被同一个 CPU 处理,将存储“五元组对应关系”的内存数据库在不同的 CPU 核心上隔离开,这样就可以利用多个 VIP 来实现整体系统容量的线性提升³。
当单网卡性能极限来到了 50G,该怎么将集群性能提升到 200G 呢?插四块网卡行不行呢?理论上可行,但是现实中这么大的流量的系统一定要使用架构来提升系统容量,因为还需要解决高可用问题。
下面我们从左到右对这个架构进行解析。
基于 DNS 技术做单域名多 ip 扩容曾是第一代负载均衡技术:朴素的 DNS 协议可以将用户的终端流量直接导向全国多个机房,实现真·性能倍增,这种技术特别适合 Web 1.0 时代的静态网页,也适合搜索引擎等没有数据同步需求的服务。
在当年电信、网通、铁通、教育网之间只有 40G 小水管的年代,DNS 技术极大地提升了普通用户获取网络资源的速度,提升了用户体验:引导每个运营商的用户访问放在该运营商机房的服务器,可以实现“手搓 CDN 架构”。最后一篇文章我们还会谈到 DNS 技术在终极高可用架构中的价值。
经过 DNS 拆分,每个路由拥有一个公网 ip,承载 100G 带宽,注意,此处的路由真的是路由,并不是网关,它只需要告诉每一个数据包该到哪儿去即可。这个架构中的网关其实是后面的 LVS 充当的。而硬件路由设备承受住 200G 带宽甚至都不需要上高端的数据中心核心设备。
上图中的路由_1
和路由_2
采用支持 ECMP 的硬件设备或者软件路由来充当,他们会把流量平均分给两个交换机。每台交换机承载 100G 带宽,对交换机来说简直就是洒洒水,2 万块人民币的硬件交换机就能接近 24 x 100G 全线速交换(二手的甚至只要六千块)。
每台 LVS 服务器都安装双口 100G 网卡 2 张,共有四个网口,这样单机可以实现 50G x 2 的极限性能。每个网卡上面的两个网口,分别连接两台交换机,可以在实现了高可用的同时保证协议速度(线速)不会成为瓶颈。
大家可以看到,从左至右,整个架构的每一层的每一个节点,都和左边一层的所有节点进行连接,这种全冗余架构可以满足在任意一台设备宕机的情况下,整个系统依然可用,甚至系统容量都能维持不变。
如果某台路由宕机,则另一台路由会将它的公网 ip 接过来,可以实现分钟级故障恢复(主要是公网路由表可能更新缓慢)。
如果某台交换机宕机,则左侧的路由通过 ECMP 及时调整路由配置,可以实现秒级切换。
如果某台 LVS 服务器宕机:Keepalived 机制会让 Standby 设备在 1 秒之内顶上。
对于整个系统来说,四台安装了双网卡的 LVS 服务器,2 主 2 备,在两个公网 ip 入口的情况下,可以实现 50G x 2 x 2 = 200G 的总带宽,并且任意一台设备宕机不影响系统总容量。
200G 并不是这个系统的极限,如果我们让一组的两台 LVS 服务器使用两个 VIP 做互为主备的双活的话,可以把整个系统的容量提升到理论极限 400G。下面我们分析一下各种单项资源的性能极限:
还记得上面那台 100 万的硬件负载均衡器吗,他的最大 L4 带宽只有 40G,而我们这一套 200/400G 的设备要多少钱呢?
1x2 + 2x2 + 3x4 = 18万
花 18 万搭建一套图中的设备,不仅可以搞出一套 200G 的集群,而且图中的路由和交换机还有大量的容量可以用于其他业务。
更重要的是:LVS 集群相比于硬件负载均衡设备是可以轻松控制的,是可编程的,这对于右侧上游服务器的网络架构规划十分有利。对于云计算厂商来说,可以开发更丰富的功能来提供更复杂的服务(例如计算和存储分离的数据库),提升硬件资源的利用率,同时可以提供更复杂的功能给云平台用户使用:
软件带来的无限可能才是这套配置最核心的价值!
这是 H3C 集团 ComwareV7 通用操作系统的架构图,当下 H3C 正在销售的产品中,除了网络边界设备(如防火墙)外,其余几乎所有的交换机、AC、AP 等以局域网为主战场的设备已经全面采用了该系统。和上一代 V5 相比,最大的变化就是把系统内核切换到了 Linux Kernel。
这张图中最重要的就是那根“细细的红线”:网络管理进程完全位于用户态。这其实就是 DPDK 思想:传统的 UNIX 网络模型已经无法应付单机 10G 的速度了,需要读写内存的进程切换太慢了,必须要从底层网络数据处理流程上革命:抛弃操作系统提供的网络栈,直接在用户态接管所有网络流量,实现更高性能。
为了提高软件稳定性,H3C 也在系统内开发了一些高可用技术,和我们负载均衡集群高可用的设计思想不谋而合,异曲同工:
在机房硬件设备中,最容易损坏的肯定是磁盘(硬盘),因为它是在不断磨损的,即便是 SSD 也会随着时间的流逝寿命逐渐丢失,哪怕装在盒子里不通电也一样。但是硬盘之后,容易宕机或者损坏的是什么大家应该就猜不到了。
首先是断电:数据中心因为各种问题断电是最常见的故障,这个故障的概率甚至要高于软件引发的故障和电源适配器的故障。
其次是内存失效:内存以及内存插槽,内存电路,似乎是今天服务器硬件之中除了磁盘之外最容易坏的东西,马上就要进入 DDR5 时代,内存功耗又上了一个台阶,恐怕故障率会进一步上升。
然后是网络线材和供电线材接口的问题,时间长了松了或者进灰了,就会丢包或者重启。2011 年震惊世界的中微子超光速事件,就是插头松了导致的。
最后是高温引发的宕机:特别是 GPU 服务器,一旦服务器或者机房的散热系统出现问题,服务器很容易就主动限制性能甚至关机。
其它的,硬件网络设备(路由器交换机)故障、彻底挖断光纤、CPU 损坏、电源转换器寿命耗尽、主板电池故障、地震火灾洪水等,可能在一台服务器的上架寿命之中都完全无法遇到。
通过本文构建的这个 200/400G 负载均衡集群,配合多个应用网关,以及后面海量的物理服务器,我们终于成功实现了一百万 QPS 的目标。但是,这就是一百万 QPS 的全部了吗?当然不是,这只是 web 服务层面的百万 QPS,在真实世界中,数据库才是那个最难解决的单点。
出自:https://github.com/johnlui/PPHC
本文由 mdnice 多平台发布