[译] 条分缕析拆解现代网络负载均衡和代理技术
sfxe4820
7年前
<p>关于现代网络负载均衡和代理(proxy)的介绍性资料很少,这件事引起了我的注意。为什么会这样呢?构建一个可靠的分布式系统时,负载均衡是一个非常核心的概念。但可惜的是,搜索发现关于负载均衡和服务代理的内容很少。维基百科文章只包含了一些概念,没有对该主题的详细介绍,尤其是与现代微服务架构相关的。</p> <p>本文试图通过对现代网络负载均衡和代理的简单介绍,来弥补这部分信息的缺乏。为了保持文章的长度,尽量将复杂的话题浓缩成简单的概述。</p> <p><strong>1</strong></p> <p><strong>什么是网络负载均衡和代理?</strong></p> <p>维基百科这样定义负载均衡:</p> <p>在计算中,负载均衡可以改善在多个计算机资源(如计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器)上的工作负载分布。负载均衡旨在优化资源的使用,最大吞吐量,及最小响应时间,避免任何单一资源的过载。通过使用多个组件而不是单个组件,负载均衡通过冗余来提高可靠性和可用性。负载均衡通常涉及专用软件和硬件,例如多层交换机或域名系统服务器进程。</p> <p>以上定义适用于计算的各个方面,而不仅仅是网络。操作系统使用负载均衡在物理处理器之间安排任务,诸如Kubernetes之类的容器编排者使用负载均衡来计划跨计算集群的任务,网络负载均衡通过调用可用后端来平衡网络任务。以下内容仅涵盖网络负载均衡。</p> <p><img src="https://simg.open-open.com/show/3226b1152995b8f2000e2867e0743f55.png"></p> <p>图 1: 网络负载均衡描述</p> <p>图1展示了网络负载均衡高层次的概览。一些客户端从后端请求资源。负载均衡器位于客户端和后端之间,在更高层次执行关键任务:</p> <ul> <li> <p>服务发现: 在系统中哪些后端可用?地址是多少?(换句话说,负载均衡器如何与它们通信?)</p> </li> <li> <p>健康检查: 在系统中目前哪些后端是健康的,可以接受请求?</p> </li> <li> <p>负载均衡: 用什么样的算法把独立的个人请求发给健康的后端?</p> </li> </ul> <p>在分布式系统中正确使用负载均衡会带来如下好处:</p> <ul> <li> <p>命名抽象: 客户端可以通过预定义的机制来寻址负载均衡器,而不是每个客户端都需要了解每个后端(服务发现),然后将名称解析的任务委托给负载均衡器。预定义的机制包括内置库和众所周知的DNS/IP/端口地址,后面会有详细的讨论。</p> </li> <li> <p>容错: 通过健康检查和各种算法技术,负载均衡器的路由方法可以绕过坏的或者超负载的后端。这也意味着运维人员可以随时优先修复后端错误。</p> </li> <li> <p>低成本和高性能: 分布式系统网络一致性比较差。系统可能会横跨不同的网络区域。在一个区域内,网络之间通常以相对小的带宽建立的。而在不同的区域之间,网络大带宽成为常态(带宽的大小是指通过NIC使用的带宽量占路由器之间可用带宽的百分比)。智能的负载均衡可以尽可能保持区域内的请求流量,从而提高性能(低延迟)并降低整体系统成本(减少区域间的带宽和光纤)。</p> </li> </ul> <p>负载均衡器VS代理</p> <p>在谈论到网络负载均衡器,Load Balancer 和 Proxy 两个术语在行业内可以互换使用。在本文中也把两者视为一致的表达。(不过,不是所有的代理都是负载均衡器,但绝大多数代理都将负载均衡作为主要功能)。</p> <p>一些人会争辩说,当负载均衡器作为嵌入式客户端库的一部分实现时,这种负载均衡器并不是真正的代理。这种区分其实添加了不必要的复杂性。本文会详细讨论负载均衡器的拓扑类型,嵌入式负载均衡器是代理的一个特例,应用通过嵌入式库进行代理,嵌入式库与应用进程外的负载均衡器整体抽象是一致的。</p> <p>L4(连接/会话)负载均衡</p> <p>业界讨论负载均衡时,解决方式往往分为两类:L4 和 L7。指的是OSI模型的第四层和第七层。OSI模型包括传统的第四层协议(如TCP和UDP),还包含各种不同OSI层的协议。换句话说,如果 L4 TCP负载均衡器也支持 TLS 终止,这不就是 L7负载均衡器么?</p> <p><img src="https://simg.open-open.com/show/d842f9c40e6d00ab1c4ca23bd9eb57ad.png"></p> <p>图2:TCP L4 终止负载平衡</p> <p>图2展示了传统的L4 TCP负载均衡器。在这种情况下,客户端与负载均衡器建立TCP连接,负载均衡器终止连接(即直接响应SYN),选择一个后端,并与后端建立新的TCP连接(即发起新的SYN)。</p> <p>本节的关键是L4负载均衡器通常只在 L4 TCP / UDP连接/会话上运行。因此,负载平衡器负责操作字节,并确保来自同一会话的字节转发到同一后端。L4负载平衡器并不知道通信中的任何应用细节。这些字节可能是 HTTP,Redis,MongoDB或任何其他应用协议。</p> <p>L7(应用)负载平衡</p> <p>L4负载均衡简单,能看到广泛使用。人们为什么放弃L4负载均衡,来研究L7(应用)负载均衡?以下是L4具体的案例:</p> <ul> <li> <p>两个gRPC / HTTP2 客户端通过L4负载均衡器与后端建立连接。</p> </li> <li> <p>L4负载均衡器为每个接入的TCP连接建立一个传出的TCP连接,这样就产生了两个传入和两个传出连接。</p> </li> <li> <p>但是,客户端A每分钟发送 1个请求(RPM),而客户端B通每秒发送50个请求(RPS)。</p> </li> </ul> <p>在上述场景中,后端选择处理客户端B请求是选择客户端A请求负载的大约3000倍。这是一个很大的问题,打破了负载均衡的目的。需要注意的是这个问题发生在任何复用,保持存活状态的协议。(复用意味着通过单个L4连接多次发送应用程序请求,保持存活就是没有活动请求时不关闭连接)。出于效率的考虑,所有现代协议都在不断发展,既要复用也要存活(创建连接通常是昂贵的,特别是用TLS进行加密连接时),所以L4负载均衡器随着时间的推移,负载失衡的情况更加明显。这个问题在L7负载均衡器中得到解决。</p> <p><img src="https://simg.open-open.com/show/a6b32189029c3c84a108cedb62e5b313.jpg"></p> <p>图3:HTTP / 2 L7终端负载均衡</p> <p>图3展示了L7 HTTP/2负载平衡器。客户端与负载均衡器只建立一个 HTTP/2 TCP连接,连接两个后端。当客户端向负载均衡器发送两个HTTP/2 流时,流1被发送到后端1,流2被发送到后端2。因此,即使差别很大的请求负载的多路复用客户端也将被有效地平衡到不同的后端。这就是L7负载平衡对于现代协议的重要性所在。(L7负载平衡由于能够检查应用流量,而产生大量好处,后面会更详述)。</p> <p>L7负载均衡和OSI模型</p> <p>正如L4负载平衡部分所述,使用OSI模型描述负载均衡功能是有问题的。原因在于L7本身包含多个离散的负载均衡抽象层。例如,对于HTTP流量,请考虑以下子层:</p> <ul> <li> <p>可选的传输层安全性(TLS)。网络界对于TLS 属于OSI模型哪一层有争论。为了方便,我们考虑将TLS放在 L7。</p> </li> <li> <p>物理HTTP协议(HTTP / 1或HTTP / 2)。</p> </li> <li> <p>逻辑HTTP协议 (Header、Body 和 Trailer) 。</p> </li> <li> <p>消息传递协议(gRPC,REST等)。</p> </li> </ul> <p>一个复杂的L7负载均衡器要提供与上述每个子层有关的功能。另L7负载均衡器可能只有一小部分功能属于OSI模型中L7层。简而言之,L7负载平衡器的功能远比L4类型复杂得多。(HTTP、 Redis、Kafka、MongoDB等都是应用L7 协议的例子,它们受益于L7负载均衡)。</p> <p><strong>2</strong></p> <p><strong><strong>负载均衡器功能 </strong> </strong></p> <p>在本节中将总结负载均衡器提供的高级功能,并非所有负载均衡器都提供全部功能。</p> <p>服务发现</p> <p>服务发现是负载平衡器确定可用后端的过程,实现的方式有很多种,一些例子包括:</p> <ul> <li> <p>静态配置文件。</p> </li> <li> <p>DNS。</p> </li> <li> <p>Zookeeper,Etcd,Consul等。</p> </li> <li> <p>Envoy的通用数据平面API。</p> </li> </ul> <p>健康检查</p> <p>运行状况检查是负载均衡器确定后端是否可用来为流量提供服务的过程。健康检查一般分为两类:</p> <ul> <li> <p>主动式:负载平衡器将定期发送ping(例如,对/healthcheck端点的HTTP请求)到后端,并用它来衡量健康状况。</p> </li> <li> <p>被动式:负载均衡器从主数据流中检测健康状况。例如,如果连续出现三个连接错误,则L4负载均衡器会认为后端是不健康的。如果一行中有三个HTTP 503响应代码,则L7负载均衡器会认为后端是不健康的。</p> </li> </ul> <p>负载均衡</p> <p>负载均衡器必须实际平衡负载!当给定一组健康的后端时,选择哪个后端处理请求?负载平衡算法是一个活跃的研究领域,从简单的算法(如随机选择和循环算法)到考虑可变延迟和后端负载的更复杂的算法。考虑到其性能和简单性,最流行的负载均衡算法是二节点最小请求负载均衡(power of 2 least request load balancing)。 </p> <p>粘滞会话 <strong>(</strong> <strong>Sticky sessions</strong> <strong>)</strong></p> <p>在某些应用中,同一会话的请求到达相同的后端是很重要的。这与缓存,临时复杂状态等有关。会话的定义各不相同,可能包括HTTP Cookie,客户端连接的配置或其他属性。许多L7负载平衡器支持会话粘连。会话粘性本质上是脆弱的(后端保存的会话可能会失效),所以在设计系统的时候减少对它们的依赖。</p> <p>TLS终止</p> <p>关于TLS,它在边缘服务和服务间通信方面值得肯定。因此,许多L7负载均衡器会执行大量的TLS处理,包括终止,证书验证和保存,使用SNI的证书服务等。</p> <p>可观察性</p> <p>正如谈话中所强调的:“可观察性,可观察性,可观察性”。网络本质上是不可靠的,负载均衡器通常负责导出统计信息,跟踪信息和记录日志,帮助运营人员找出问题所在,从而解决问题。最先进的负载平衡器可观察性输出包括数字统计,分布式跟踪和可定制的日志记录。增强的可观察性不是免费的; 负载平衡器必须做很多附加的工作来完成它。至于,负面影响,相对带来的好处,几乎不值一提。</p> <p>安全性和 <strong>DoS</strong> <strong>防范</strong></p> <p>特别是在边缘部署拓扑(见下文)中,负载均衡器通常实施各种安全功能,包括速率限制,身份验证和DoS防范(例如,IP地址标记和识别,缓送 Tarpitting 等)。</p> <p>配置和控制面板</p> <p>负载平衡器需要配置。在大规模部署中,这是一项重要工作。一般来说,配置负载均衡器的系统被称为“控制面板”,并且在其实现中变化很大。</p> <p><strong>3</strong></p> <p><strong><strong>负载均衡器拓扑的类型</strong> </strong></p> <p>前面介绍了负载平衡器的概要,L4和L7负载平衡器之间的区别以及负载均衡器特性,接下来将转向部署负载均衡器的各种分布式系统拓扑。(以下每种拓扑均适用于L4和L7负载均衡器)。</p> <p>中间代理</p> <p><img src="https://simg.open-open.com/show/3226b1152995b8f2000e2867e0743f55.png"></p> <p>图4:中间代理负载均衡拓扑</p> <p>图4所示的中间代理拓扑是大多数读者最熟悉的负载均衡一种方式。这一类包括Cisco,Juniper,F5等硬件设备; 云软件解决方案,如亚马逊的ALB和NLB以及Google的 Cloud Load Balancer ; 以及HAProxy,NGINX和Envoy等纯软件自主托管解决方案。中间代理解决方案使用简单。通常,用户通过DNS连接到负载均衡器,不需要担心其他任何事情。中间代理解决方案的特点是代理(即使是集群)是单一的故障点,也是扩展的瓶颈。中间代理通常是一个让运维变得困难的黑匣子。当问题出现时,是在客户端还是物理网络?在中间代理还是后端?这很难说。</p> <p>边缘代理</p> <p><img src="https://simg.open-open.com/show/9e37ea77c9f5fadb3182e96879f102bf.png"></p> <p>图5:边缘代理负载平衡拓扑</p> <p>图5所示实际上只是中间代理拓扑的一种变体,负载均衡器通过Internet访问。在这种情况下,负载均衡器通常必须提供附加的“API网关”功能,如TLS终止,速率限制,身份验证和复杂的流量路由。边缘代理的优缺点与中间代理相同。需要注意的是,在面向Internet的大型分布式系统中部署专用边缘代理通常是不可避免的。客户端通常需要使用服务所有者无法控制的任意网络库(后面会讨论嵌入式客户端库或附属代理拓扑结构不能直接在客户端上运行)通过DNS访问系统。另外,由于安全原因,希望具有单个网关,通过该网关,所有面向互联网的流量进入系统。</p> <p>嵌入式客户端库</p> <p><img src="https://simg.open-open.com/show/1899daf428b12552cb183b50d5c0e91a.png"></p> <p>图6:通过嵌入式客户端库进行负载平衡</p> <p>为了避免中间代理拓扑中固有的单点故障和扩展问题,更复杂的基础设施已经开始将负载均衡器直接嵌入到服务库中,如图6所示。支持的功能库有很大的不同,但是这个类别中最知名和最丰富的功能包括Finagle,Eureka / Ribbon / Hystrix和gRPC(松散地基于称为Stubby的内部Google系统)。基于库的解决方案的主要功能是将负载均衡器的所有功能完全分配给每个客户端,从而消除之前描述的单点故障和扩展问题。基于客户端库的解决方案的主要内容是客户端库必须每种语言调用。分布式架构正变得越来越“多语言”(多语言)。在这样的环境下,用许多不同的语言来重新实现一个非常复杂的网络库的成本会变得过高。最后,在大型服务体系结构中部署库升级可能会非常痛苦,这使得很多不同版本的库将在生产中同时运行,</p> <p>综上所述,上面提到的这些库对于那些能够限制编程语言扩散并克服库升级难题的公司来说是成功的。</p> <p>Sidecar代理</p> <p><img src="https://simg.open-open.com/show/9d0a6f75286f824d1ad71598f71debb4.jpg"></p> <p>图7:通过sidecar代理进行负载平衡</p> <p>嵌入式客户端库负载平衡器拓扑的一个变种是图7中所示的辅助代理拓扑。近年来,这种拓扑已经被普遍推广为“服务网格”(Service Mesh)。Sidecar代理背后的思路是,以跳过一个不同的过程的代价来承担轻微的延迟,嵌入式库的所有好处都可以在没有任何编程语言锁定的情况下获得。在撰写本文时,最受欢迎的sidecar代理负载平衡器是Envoy,NGINX,HAProxy和Linkerd。</p> <p>负载均衡器拓扑的总结和优缺点</p> <ul> <li> <p>中间代理拓扑是最简单的负载平衡拓扑。缺点是:单点故障,伸缩瓶颈和黑箱操作。</p> </li> <li> <p>边缘代理拓扑与中间代理类似,但通常无法避免。</p> </li> <li> <p>嵌入式客户端库拓扑提供了最好的性能和可扩展性,但是需要在每种语言中实现该库,并跨所有服务升级库。</p> </li> <li> <p>Sidecar代理拓扑性能比嵌入式客户端库拓扑弱,但不受任何限制。</p> </li> </ul> <p>总体而言,sidecar代理拓扑(服务网格)正在逐渐取代所有其他的服务。流量进入服务网格之前,始终需要边缘代理拓扑。</p> <p>4</p> <p><strong>L4负载均衡的现状 </strong></p> <p>L4负载均衡器 <strong>还有用吗</strong> <strong>?</strong></p> <p>本文讨论了L7负载平衡器如何用于现代协议,后面还会讨论L7负载平衡器的特性。这是否意味着L4负载平衡器没用了?没有!尽管在我看来,L7负载均衡器最终将完全取代L4负载均衡器进行服务间通信,但是L4负载均衡器对边缘通信仍然很重要。因为几乎所有现代大型分布式架构都使用两层L4 / L7负载平衡架构处理互联网流量。在L7负载均衡器之前在边缘部署中部署专用L4负载均衡器的好处是:</p> <ul> <li> <p>L7负载均衡器执行的应用程序流量的分析,转换和路由选择要复杂得多,所以它们可以处理相对于经过优化的L4负载均衡器能够处理的相对较小的原始流量负载(以每秒数据包和每秒字节数衡量)。这一现实通常使得L4负载平衡器成为处理某些类型的DoS攻击(例如,SYN flood,通用包flood攻击等)的更好位置。</p> </li> </ul> <ul> <li> <p>L7负载均衡器往往比L4负载平衡器更积极地开发,部署更频繁,并且具有更多的缺陷。有一个L4负载均衡器,可以在L7负载平衡器部署期间执行健康检查和排空,这比现代L4负载平衡器(通常使用BGP和ECMP)(以下更多)中使用的部署机制要容易得多。最后,因为L7负载平衡器功能的复杂性更容易出现错误,所以使用绕开故障和异常的L4负载平衡器产生更稳定的整体系统。</p> </li> </ul> <p>下面将介绍几种不同的中间/边缘代理L4负载均衡器的设计。这些设计不适用于客户端库和Sidecar拓扑。</p> <p>TCP / UDP <strong>终端</strong> <strong>负载均衡器</strong></p> <p><img src="https://simg.open-open.com/show/d842f9c40e6d00ab1c4ca23bd9eb57ad.png"></p> <p>图8:L4终端负载均衡器</p> <p>仍在使用的第一类L4负载均衡器是图8所示的终端负载均衡器。这类负载均衡器,使用两个离散的TCP连接:一个在客户端和负载均衡器之间,另一个在负载均衡器和后端之间。</p> <p>L4终端负载均衡器仍然有两个原因:</p> <ol> <li> <p>实现相对简单。</p> </li> <li> <p>靠近客户端的连接终端(低延迟)对性能有很大的影响。具体来说,如果终端负载均衡器可以放置在使用有损网络(例如蜂窝)的客户端附近,那么在将数据转移到可靠的光纤传输到其最终位置之前,容易发生重传。换句话说,这种负载平衡器适用于存在点(POP)场景下的原始TCP连接。</p> </li> </ol> <p>TCP / UDP直通负载均衡器</p> <p><img src="https://simg.open-open.com/show/6816e4f4bce30d3a18860360a568fed7.png"></p> <p>图9:L4直通负载均衡器</p> <p>第二种类型的L4负载均衡器是图9所示的直通负载均衡器。在这种类型的负载均衡器中,TCP连接不会被负载均衡器终止。而是在连接跟踪和网络地址转换(NAT)发生后,将每个连接的数据包转发到选定的后端。首先,我们来定义一下连接跟踪和NAT:</p> <ul> <li> <p>连接跟踪:跟踪所有活动的TCP连接状态的过程。这包括握手是否完成,是否收到FIN,连接空闲多久,连接选择了哪个后端等等。</p> </li> </ul> <ul> <li> <p>NAT:NAT是使用连接跟踪数据在通过负载均衡器时更改数据包的IP /端口信息的过程。</p> </li> </ul> <p>使用连接跟踪和NAT,负载平衡器可以将大部分原始TCP流量从客户端传递到后端。例如,假设客户正在交谈,1.2.3.4:80而选定的后端位于10.0.0.2:9000。客户端TCP数据包将到达负载均衡器at 1.2.3.4:80。然后负载均衡器将交换数据包的目标IP和端口10.0.0.2:9000。它还会将数据包的源IP与负载均衡器的IP地址进行交换。因此,当后端在TCP连接上响应时,数据包将返回到负载平衡器,在那里进行连接跟踪并且NAT可以在反向再次发生。</p> <p>为什么会使用这种负载均衡器来代替上一节中描述的终端负载均衡器呢?几个原因:</p> <ul> <li> <p>性能和资源使用: 由于直通负载均衡器不是终止TCP连接,所以不需要缓冲任何TCP连接窗口。每个连接存储的状态量非常小,通常通过高效的散列表查找来访问。因此,直通负载均衡器通常可以处理比终端负载均衡器大得多的活动连接数和数据包数(PPS)。</p> </li> </ul> <ul> <li> <p>允许后端执行拥塞控制:TCP拥塞控制是因特网上的端点节制发送数据的机制,从而不会压倒可用带宽和缓冲区。由于直通负载均衡器不会终止TCP连接,因此不参与拥塞控制。这个事实允许后端根据他们的应用使用情况使用不同的拥塞控制算法。它还可以更容易地进行拥塞控制变更的实验(例如,最近的BBR部署)。</p> </li> <li> <p>形成直接服务器返回(DSR)和群集L4负载平衡的基准: 更高级的L4负载平衡技术(如DSR和使用分布式一致性散列的群集(以下各节中讨论))需要直通负载平衡。</p> </li> </ul> <p>直接服务器返回( <strong>Direct Server Return</strong> <strong>,</strong> <strong>DSR</strong> <strong>)</strong></p> <p><img src="https://simg.open-open.com/show/88c81d60f20e648a9304a3f1814b53e7.png"></p> <p>图10:L4直接服务器返回(DSR)</p> <p>直接服务器返回(DSR)负载平衡器如图10所示。DSR构建在上一节中介绍的直通负载均衡器上。DSR是一种优化,只有入口/请求数据包才能通过负载均衡器。出口/响应数据包在负载平衡器周围直接返回到客户端。执行DSR很有趣的主要原因是,在许多工作负载中,响应流量对请求流量(例如,典型的HTTP请求/响应模式)产生了不满。假设10%的流量是请求流量,90%的流量是响应流量,如果使用DSR的负载均衡器为1/10的容量可以满足系统的需求。由于历史上负载平衡器非常昂贵,因此这种优化可能会对系统成本和可靠性产生重大影响。DSR负载均衡器将直通负载均衡器的概念扩展如下:</p> <ul> <li> <p>负载平衡器通常仍然执行部分连接跟踪。由于响应数据包不会遍历负载均衡器,因此负载均衡器将不会意识到完整的TCP连接状态。但是,负载均衡器可以通过查看客户端数据包并使用各种类型的空闲超时来强烈推断状态。</p> </li> <li> <p>负载均衡器通常使用通用路由封装(GRE)来封装从负载均衡器发送到后端的IP数据包,而不使用NAT 。因此,当后端收到封装的数据包时,可以对其进行解封装,并知道客户端的原始IP地址和TCP端口。这允许后端直接响应客户端,而无需响应数据包流经负载平衡器。</p> </li> <li> <p>DSR负载平衡器的一个重要组成部分是后端参与负载均衡。后端需要有一个正确配置的GRE隧道,根据网络设置的低层细节,可能需要自己的连接跟踪,NAT等。</p> </li> </ul> <p>请注意,在直通负载均衡器和DSR负载均衡器设计中,可以通过负载均衡器和后端来设置连接跟踪,NAT,GRE等多种方式。</p> <p>通过高可用性配对的容错</p> <p><img src="https://simg.open-open.com/show/3713504bbfa50caea06673e5c275e695.png"></p> <p>图11:通过HA对和连接跟踪的L4容错</p> <p>到目前为止,我们一直在考虑L4负载平衡器的设计。直通和DSR负载平衡器都需要负载均衡器本身的一些连接跟踪和状态。如果负载平衡器死了怎么办?如果负载平衡器的单个实例死亡,则所有通过负载平衡器的连接将被切断。取决于应用程序,这可能会对应用程序性能产生重大影响。</p> <p>历史上,L4负载均衡器是从典型供应商(Cisco,Juniper,F5等)购买的硬件设备。这些设备非常昂贵,处理大量的流量。为了避免单个负载均衡器发生故障切断所有连接,并导致大量应用程序中断,负载均衡器通常部署在高可用性配对中,如图11所示。典型的HA负载均衡器设置具有以下设计:</p> <ul> <li> <p>一对HA边缘路由器为虚拟IP(VIP)提供服务。这些边缘路由器使用边界网关协议(BGP)宣布虚拟IP 。主边缘路由器具有比备份更高的BGP权重,因此在稳定状态下,它服务所有流量。(BGP是一个非常复杂的协议; 就本文而言,考虑BGP是网络设备宣布可以从其他网络设备获取流量的机制,并且每个链路都可以具有优先考虑链路流量的权重)。</p> </li> <li> <p>同样,主L4负载均衡器向边缘路由器宣布自己的BGP权重高于备份,因此在稳定状态下,它将服务所有流量。</p> </li> <li> <p>主负载均衡器交叉连接到备份,并共享其所有连接跟踪状态。因此,如果主负载宕机,备份可以接管处理所有活动的连接。</p> </li> <li> <p>两台边缘路由器和两台负载均衡器都是交叉连接的。这意味着如果其中一个边缘路由器或负载平衡器中的一个死亡,或者由于某种其他原因撤消BGP通知,备份可以接管所有通信。</p> </li> </ul> <p>上面的设置是目前具有高流量的互联网应用还在使用的方式。但是,上述方法有很大的缺点:</p> <ul> <li> <p>考虑到容量使用情况,虚拟 IP (VIP)必须在HA负载平衡器对之间正确分片。如果单个VIP超出单个HA对的容量,则需要将VIP分成多个VIP。</p> </li> <li> <p>系统的资源使用情况很差。50%的容量在稳定状态下闲置。鉴于历史上硬件负载平衡器非常昂贵,这导致大量闲置资本。</p> </li> <li> <p>现代分布式系统设计比主动/备份提供更高的容错能力。例如,最佳地,系统应该能够同时遭受多个故障并继续运行。如果主动和备用负载均衡器同时死亡,则HA负载均衡器对可能会发生完全故障。</p> </li> <li> <p>来自供应商的专有大型硬件设备非常昂贵,并导致供应商锁定。通常希望用可商购计算服务器构建的可横向扩展的软件解决方案替代这些硬件设备。</p> </li> </ul> <p>通过具有分布式一致散列的集群进行容错和扩展</p> <p><img src="https://simg.open-open.com/show/29cd02a42d5d62d7a7cc92d77f6030d3.png"></p> <p>图12:L4容错和通过集群负载平衡器和一致性哈希的扩展</p> <p>上一节介绍了通过HA对的L4负载平衡器容错以及该设计中固有的问题。从21世纪初到中期,大型互联网基础设施开始设计和部署新的大规模并行L4负载平衡系统,如图12所示。这些系统的目标是:</p> <ul> <li> <p>减轻上一节中描述的HA对设计的所有缺点。</p> </li> <li> <p>从供应商的专有硬件负载平衡器转移到使用标准计算服务器和NIC构建的商品软件解决方案。</p> </li> </ul> <p>这个L4负载均衡器设计最好称为容错和扩展,通过集群和分布式一致的散列。它的工作原理如下:</p> <ul> <li> <p>N个边缘路由器以相同的BGP权重宣布所有Anycast VIP。等价多路径路由(ECMP)用于确保通常来自单个流的所有数据包到达相同的边缘路由器。流程通常是源IP /端口和目标IP /端口的四元组。(简而言之,ECMP是一种使用一致散列在一组相同加权的网络链路上分发数据包的方法)。尽管边缘路由器本身并不特别关心哪个分组到达哪里,但是通常优选的是,来自一个流的所有分组都经过相同的一组链路,以避免乱序分组,从而降低性能。</p> </li> </ul> <ul> <li> <p>N个L4负载均衡器机器以与边缘路由器相同的BGP权重宣布所有的VIP。再次使用ECMP,边缘路由器将通常为流选择相同的负载平衡器机器。</p> </li> </ul> <ul> <li> <p>每个L4负载均衡器机器通常会执行部分连接跟踪,然后使用一致的哈希来为流选择一个后端。GRE用于封装从负载均衡器发送到后端的数据包。</p> </li> </ul> <ul> <li> <p>DSR然后被用来通过边缘路由器直接从后端发送数据包到客户端。</p> </li> </ul> <ul> <li> <p>L4负载均衡器使用的实际一致性散列算法是一个活跃的研究领域。主要围绕均衡负载进行权衡,最小化延迟,最大限度地减少后端更改期间的中断, 并最大限度地减少内存开销。关于这个主题的完整讨论超出了本文的范围。</p> </li> </ul> <p>让我们看看上面的设计是如何缓解HA对方法的所有缺点的:</p> <ul> <li> <p>新的边缘路由器和负载平衡器机器可以根据需要添加。在添加新机器时,每层都使用一致的散列来尽可能减少受影响的流量。</p> </li> </ul> <ul> <li> <p>系统的资源使用可以按照需要高速运行,同时保持足够的突发容限和容错。</p> </li> </ul> <ul> <li> <p>边缘路由器和负载平衡器现在都可以使用商用硬件来构建,而传统硬件负载平衡器的成本只是其中的一小部分(下面会详细介绍)。</p> </li> </ul> <ul> <li> <p>通常被问及这个设计的一个问题是“为什么边缘路由器不通过ECMP直接与后端对话?为什么我们需要负载平衡器?“其原因主要是减少DoS和后端操作的简化。如果没有负载平衡器,每个后端都必须参与BGP,并且执行滚动部署的时间将更加困难。</p> </li> </ul> <p>所有现代化的L4负载均衡系统都在朝着这种设计方向发展(或其他变体)。最著名的两个例子是Google的Maglev和Amazon 的 <strong>网络负载均衡器(NLB)</strong> 。目前还没有实现这种设计的OSS负载平衡器,但是,我知道有一家公司计划在2018年将其发布到OSS。我对这个版本感到非常兴奋,因为现代L4负载平衡器是一个至关重要的部分在网络空间中缺少OSS。</p> <p>5</p> <p><strong>L7负载平衡的现有技术状态 </strong></p> <p>在过去的几年中,L7负载平衡器/代理的发展已经复苏。随着分布式系统中的微服务架构的不断推进,这方面也在不断进步。从根本上说,固有故障的网络在使用更频繁时变得更加难以有效地运行。而且,自动扩展,容器调度等等的出现意味着在静态文件中配置静态IP的日子早已不复存在。系统不仅要利用网络,还要变得更加动态,需要负载平衡器的新功能。本节将简要概述在现代L7负载平衡器的最新发展。</p> <p>协议支持</p> <p>现代L7负载平衡器为许多不同的协议增加了明确的支持。负载平衡器对于应用程序流量的知识越多,关于可观察性输出,高级负载平衡和路由等方面可以做的更复杂的事情。例如,在撰写本文时,Envoy明确支持L7协议解析和路由用于HTTP / 1,HTTP2,gRPC,Redis,MongoDB和DynamoDB。未来可能会有更多协议被添加,包括MySQL和Kafka。</p> <p>动态配置</p> <p>如上所述,分布式系统越来越具有动态性,需要并行投资来创建动态和反应式控制系统。Istio就是这样一个例子。</p> <p>高级负载平衡</p> <p>L7负载均衡器现在通常内置对高级负载平衡功能的支持,如超时,重试,速率限制,断路,屏蔽,缓冲,基于内容的路由等。</p> <p>可观察性</p> <p>如上面有关一般负载平衡器功能的部分所述,正在部署的日益动态的系统越来越难以调试。强大的协议特定的可观测性输出是现代L7负载平衡器最重要的特性。任何L7负载平衡解决方案现在都需要输出数字统计信息,分布式跟踪和可自定义日志记录。</p> <p>可扩展性</p> <p>现代L7负载平衡器的用户通常希望轻松扩展以添加自定义功能。这可以通过写入加载到负载均衡器的可插入过滤器来完成。许多负载平衡器也支持脚本,通常通过Lua。</p> <p>容错</p> <p>L7负载均衡器的容错性如何?一般来说,我们把L7负载平衡器视为可消耗和无状态的。使用商业软件就能够对L7负载平衡器轻松水平扩展。此外,L7负载平衡器执行的处理和状态跟踪比L4复杂得多。试图建立一个L7负载平衡器的HA配对在技术上是可能的,但非常繁杂。</p> <p>总的来说,在L4和L7负载平衡领域,业界正在从HA配对转向通过一致的哈希聚合横向水平可扩展系统。</p> <p>更多</p> <p>L7负载平衡器正在以惊人的速度发展。有关Envoy提供的示例,请参阅Envoy的架构概述。</p> <p>6</p> <p><strong>全球负载均衡和集中控制平面</strong></p> <p><img src="https://simg.open-open.com/show/cff78f4ae1c52b455164632181a604e2.jpg"></p> <p>图13:全局负载平衡</p> <p>负载平衡的未来将越来越多地将单个负载平衡器视为商品设备。我认为,真正的创新和商业机会都在控制层面。图13显示了一个全局负载均衡系统的例子。在这个例子中,几个不同的事情正在发生:</p> <ul> <li> <p>每个Sidecar代理正在与三个不同区域(A,B和C)的后端进行通信。</p> </li> </ul> <ul> <li> <p>如图所示,90%的流量正被发送到区域C,而5%的流量正被发送到区域A和B。</p> </li> </ul> <ul> <li> <p>Sidecar代理和后端均向全局负载均衡器报告周期性状态。这允许全局负载均衡器做出考虑延迟,成本,负载,当前故障等的决定。</p> </li> </ul> <ul> <li> <p>全局负载均衡器使用当前路由信息周期性地配置每个边车代理。</p> </li> </ul> <p>全球负载均衡器越来越能够做复杂的事情。例如:</p> <ul> <li> <p>自动检测并绕过区域故障。</p> </li> <li> <p>应用全局安全和路由策略。</p> </li> <li> <p>使用机器学习和神经网络检测和减轻流量异常,包括DDoS攻击。</p> </li> <li> <p>提供集中的用户界面和可视化,使工程师能够理解和操作整个分布式系统。</p> </li> </ul> <p>为了实现全局负载均衡,用作数据平面的负载平衡器必须具有复杂的动态配置能力。</p> <p><strong>7</strong></p> <p><strong>从硬件到软件的演变</strong></p> <p>本文只是简单地提到了硬件和软件,主要是在L4负载平衡器HA对的历史背景下。这方面的业界趋势又是怎样呢?</p> <ul> <li> <p>历史上的路由器和负载平衡器都是昂贵的专有硬件。</p> </li> <li> <p>越来越多的专有L3 / L4网络设备正在被商用服务器硬件,商用网卡和基于IPVS,DPDK和fd.io等框架的专业软件解决方案取代。价格低于5K美元的现代数据中心机器可以使用Linux和自定义的基于DPDK的 user-space 应用,轻松饱和具有非常小数据包的80Gbps NIC。与此同时,廉价的路由器/交换机ASIC可以以惊人的总带宽和数据包速率进行ECMP路由选择,正在被打包成商品路由器。</p> </li> <li> <p>像NGINX,HAProxy和Envoy这样先进的L7软件负载平衡器也在迅速地迭代和侵入之前像F5这样的供应商领域。因此,L7负载平衡器也在积极地向商品软件解决方案迈进。</p> </li> </ul> <p>与此同时,整个行业向主流云提供商推动的IaaS,CaaS和FaaS意味着越来越多的工程师需要了解物理网络是如何工作的</p> <p>8</p> <p><strong>结论和负载均衡的未来</strong></p> <p>这篇文章的主要内容是:</p> <ol> <li> <p>负载平衡器是现代分布式系统中的关键组件。</p> </li> <li> <p>有两种负载均衡器:L4和L7。</p> </li> <li> <p>L4和L7负载平衡器都与现代架构中相关。</p> </li> <li> <p>L4负载均衡器正朝着横向可扩展的分布式一致哈希水平扩展解决方案迈进。</p> </li> <li> <p>由于动态微服务体系结构的激增,L7负载平衡器最近发展迅速。</p> </li> <li> <p>全局负载平衡和控制平面与数据平面之间的分离,是负载平衡的未来,存在大量商业机会。</p> </li> <li> <p>业界正在积极向商用OSS硬件和软件提供网络解决方案。相信像F5这样的传统负载均衡厂商将首先被OSS软件和云供应商所取代。传统的路由器/交换机厂商,如Arista / Cumulus /等。短期会有好的发展,但最终也将被公有云供应商和自研物理网络所取代。</p> </li> </ol> <p>总的来说,现在是计算机网络的一个激动人心的时代!大多数系统开始向OSS和软件方向转变,迭代速度加快。分布式系统向“无服务器”计算发展,必须继续充满活力,底层网络和负载平衡系统的复杂性也将齐头并进。</p> <p> </p> <p>来自:http://mp.weixin.qq.com/s/LwmYMenIG77m8F_YaXqIAg</p> <p> </p>