本文转载自微信公众号《董泽润的技术笔记》,作者董泽润。转载本文请联系董泽润技术笔记公众号。在计算中,LoadBalance[1]是指将一组任务分配到一组资源(计算单元)上,以使其整体处理效率更高的过程。负载均衡可以优化响应时间,避免部分计算节点不平衡过载,而其他计算节点空闲。同时,负载均衡、反向代理、网关模块的功能也大同小异,所以本文泛指LB作为所有提供类似功能的开源软件以及为什么设备需要LB上面的人都能认出来图片都是老枪。硬件负载均衡设备F5和Netscaler是上一代互联网基础设施必不可少的接入层设备。那时候lvs刚刚起步,fullnat还没有流行起来。因此需要硬件设备作为接入层LB。赶集网当时有两台设备,一主一备,设备过期时间较晚。由于成本问题,公司没有购买后续维护服务。fullnat模式的lvs代码是开源的。一般来说,公司使用lvs+nginx实现接入层:外部BGPIP,Lvs+OSPF搭建tcp四层接入层,nginx负责卸载ssl,配置各种转发逻辑。广义上讲,这里lvs和nginx都是LoadBalance软件。LB除了按照一定的算法均衡后端设备的负载外,还需要检测后端Server的存活状态,自动剔除故障节点。什么?本质就是理解tcp/ip模型和底层原理。如上图所示,共有七层,包括物理层、Mac层、IP层、TCP层、HTTP/HTTPS。每一层都有不同的头部,然后将数据封装起来传递给下一层。发送数据的逻辑与接收数据的逻辑相反。不同的LB和模式在不同的模型中工作。比如我们常见的Nginx,往往工作在第七层。动态解析http/https协议,然后转发请求。LVS有多种模式,可以工作在二层、三层、四层。LinuxVirtualServerLinuxVirtualServer(lvs)是Linux内核自带的负载均衡器,也是目前性能最好的软件负载。均衡器之一。lvs包括ipvs内核模块和ipvsadm用户空间命令行工具。在lvs中,节点分为两种角色:DirectorServer和RealServer。DirectorServer是负载均衡器所在节点,RealServer是后端服务节点。当用户的请求到达DirectorServer后,内核netfilter机制的PREROUTING链会将发往本地IP的数据包转发到INP??UT链(即ipvs的工作链,在INPUT链上,ipvs处理数据包根据用户定义的规则(如修改目的IP和端口等),将新包发送到POSTROUTING链,再转发到RealServer。阿里很早就开源了LVS,但是最新的fullnat代码还没出,而且七牛用的lvs内核版本太低,只能用linux2.7内核,连硬件支持都很差。后面再说dpvs[2]Nat,会修改数据包的目的IP和端口,将数据包转发给RealServer(rs不需要做任务设置),此时使用DirectorServer或者LVS作为网关,在同一个LAN.数据包进来做DNAT,出去做SNAT。所有流量fic通过LVS,很容易成为瓶颈。一般用于OP性质的运维,服务正常。交通流量有问题。DR(直接路由)模式具有最佳性能。它适用于第二层。它通过修改数据包的MAC地址进行转发。属于单臂one-arm模式,所以要求二层进来的流量可以通过LVS,出去的流量直接返回。对于客户端,过去MySQL在赶集网中使用的是DR模式。该模式需要修改RealServer,配置arp_ignore和arp_announce忽略对VIP的ARP解析请求,并在lo中添加对应的VIPTunnel。这是典型的隧道模式。Fullnat解决了Nat的不足。可以无限扩展,当然也受限于单lvs的网卡和cpu性能。为了让服务获取客户端的真实IP,需要加载TOA模块,将IP写入tcp选项。DPDK+LVS=DPVSIQIYI几年前就开源了DPVS,主流公司都有自己的DPDKLBwheels。不建一个,都不好意思说自己是大公司。另外,阿里开源的fullnat模块还在linux2.6.32内核中。很多现代机器都支持不好,2021年,linux的主流内核都是4.0以上的。主要优化是DPDKbypass内核在用户态完全接管网卡,同时重写tcp/ip协议栈代码,避免了内核空间和用户空间的来回拷贝。以上就是dpvs的整体架构。里面有很多细节。有兴趣的可以上网搜索我的文章。我之前写过一系列的性能基准。据说可以达到线速。如果公司使用它,则需要对其进行调查。开源产品标榜的很好,但实际测得的数据可能不太一样。需要专人调优调度算法Round-robin(ip_vs_rr.c)Weightedround-robin(ip_vs_wrr.c)Least-connection(ip_vs_lc.c)Weightedleast-connection(ip_vs_wlc.c)Locality-basedleast-connection(ip_vs_lblc.c)基于位置的最少连接与复制(ip_vs_lblcr.c)目标散列(ip_vs_dh.c)源散列(ip_vs_sh.c)最短预期延迟(ip_vs_sed.c)从不排队(ip_vs_nq.c)磁悬浮散列(ip_vs_mh).c)以上是主流LB设备的调度算法。千篇一律的面试很有必要。一般RR简单的轮询就可以了。更复杂的需要加权。一般来说,通过滚动和划分实现的GCD的最大公分母就足够了。事实上,这还不够。比如我们线上就遇到了预热问题,服务流量特别大。新上线机器RR过来时,瞬间QPS很高,影响服务性能。表现就是GC特别频繁,请求延迟非常高。再看AWSCloud,一般我们都是以elb作为切入点。与elb、alb、clb和nlb相关的概念很多。大家可以参考官网看看区别。无非是支持四层,七层,支持路径路由,不支持。高级功能等有一些区别。因为是黑盒子,可能是c/c++写的,也可能是nginx修改的。谁知道?K8S的LBK8S中主要有三种类型:Service四层,Ingress七层,而所谓的ServiceMesh模式Service可以让你指定你需要的Service类型。默认值为ClusterIP。主要类型有:ClusterIP:通过集群内部IP暴露服务。选择该值时,服务只能在集群内访问。这也是默认的ServiceTypeNodePort:通过每个节点上的IP和静态端口(NodePort)公开服务。NodePort服务被路由到自动创建的ClusterIP服务。通过请求
