首页 > 自动化运维 > > 现代网络负载均衡和代理简介

最近引起我注意的是,很少有关于现代网络负载均衡和代理的介绍性教育资料。我心想:这怎么可能?
负载均衡是构建可靠分布式系统的核心概念之一。难道不该有高质量的信息么?我搜索并发现这些摘录确实很少。关于负载均衡和代理服务器的维基百科文章中仅包含一些概念的概述,但对各个主题的处理都不多,特别是因为它涉及到现代微服务架构。谷歌搜索到的关于负载均衡的都是一些只有时髦术语无实际内容的页面。
在这篇文章中,我试图通过提供对现代网络负载均衡和代理的介绍来补足缺乏的信息。坦率地说,这个大型主题可以写一部书。为了保持博客的篇幅,我尝试将一组复杂的主题提炼成一个简单的概述; 根据兴趣和反馈,我将考虑在稍后更详细的写关于个别主题的后续帖子。
这就是我写这篇文章的一些背景因素 - 开始吧!
Wikipedia 将负载均衡定义为:
“
在计算中,负载均衡改善了跨多个计算资源(例如计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器)的工作负载分布。负载均衡旨在优化资源使用,最大化吞吐量,最小化响应时间,并避免任何单个资源的过载。使用具有负载均衡而不是单个组件的多个组件可以通过冗余提高可靠性和可用性。负载均衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务器进程。
”
以上定义适用于计算的所有方面,而不仅仅是网络。操作系统使用负载均衡来跨物理处理器调度任务,容器编排(如Kubernetes)使用负载均衡来跨计算集群调度任务,网络负载均衡使用负载均衡来跨可用后端调度网络任务。本文的其余部分仅涵盖网络负载均衡。

图1:网络负载均衡概述
图 1显示了网络负载均衡的高级别层次的概述。一些客户端正在向一些后端请求资源。负载均衡位于客户端和后端之间,并且在高级别层次别执行几项关键任务:
在分布式系统中正确使用负载均衡可带来以下好处:
在谈论网络负载均衡器时,术语负载均衡器和代理在业内大致可互换使用。这篇文章也将这些视为一般等同。(小心并非所有代理都是负载均衡器,但绝大多数代理都将负载均衡作为主要功能)。
有些人可能会争辩说,当负载均衡作为嵌入式客户端的依赖库的一部分时,负载均衡器实际上并不是代理。但是,我认为这样区别会给已经令人困惑的话题带来不必要的复杂性。负载均衡器拓扑的类型将在下面详细讨论,但是这篇文章将嵌入式负载均衡器拓扑视为代理的特殊情况; 如果应用通过嵌入式库进行代理,那么该库与应用程序进程之外的负载均衡器是相同的抽象。
在讨论当今整个行业的负载均衡时,解决方案通常分为两类:L4和L7。这些类别涉及OSI模型的第4层和第7层。我认为我们使用的这些术语是不幸的,在下面讨论L7时就清楚了。OSI模型与复杂的负载均衡并不具备很好的相似性,其中传统的第4层协议(例如TCP和UDP),通常最终被包括在各种不同OSI的上层协议层中。即,如果L4 TCP负载均衡也支持TLS终端,它现在是L7负载均衡吗?

图2:TCP L4终端负载均衡
图 2显示了传统的L4 TCP负载均衡器。在这种情况下,客户端与负载均衡器建立TCP连接。负载均衡负责维护连接(即直接响应SYN),然后选择一个后端,并与后端建立新的TCP连接(即发送新的SYN)。该图的细节并不重要,将在下面专门讨论L4负载均衡的部分中详细讨论。
本节的关键点是L4负载均衡器通常仅在L4 TCP/UDP的连接/会话级别运行。因此,负载均衡器大致来回抽取字节,并确保来自同一会话的字节在同一后端结束。L4负载均衡器不知道它正在传输的字节的任何关于应用的细节。字节可以是HTTP,Redis,MongoDB或任何其他应用程序协议。
L4负载均衡很简单,仍然可以广泛使用。L4负载均衡有哪些缺点需要L7(应用)负载均衡来改进?以下面的L4特定案例为例:
在上一个场景中,处理客户端A相对于处理客户端B的请求量要小3000倍左右!这是一个大问题,并且这已经破坏了负载均衡的初衷。另请注意,任何多路复用,持久连接(keep-alive)的协议都会出现此问题。(多路复用意味着通过单个L4连接并发发送请求,持久连接意味着在没有请求时先不关闭连接)。由于效率原因,所有现代协议都在发展为多路复用和持久(因为创建连接通常很昂贵,特别是当使用TLS加密连接时),因此L4负载均衡器阻抗不匹配会随着时间的推移变得更加明显。此问题可以在L7负载均衡得以修复。

图3:HTTP/2 L7终端负载均衡
图 3显示了L7 HTTP/2负载均衡器。在这种情况下,客户端与负载均衡器建立单个HTTP/2 TCP连接。然后负载均衡器继续进行两个后端连接。当客户端向负载均衡器发送两个HTTP/2流时,流1被发送到后端1,而流2被发送到后端2.因此,即使多路复用不同请求负载的客户端也能在后端有效地进行均衡。这就是L7负载均衡对于现代协议如此重要的原因。(L7负载均衡由于其检查应用程序流量的能力而产生了大量额外的好处,但这将在下面更详细地介绍)。
正如我在上面关于L4负载均衡的部分所述,使用OSI模型来描述负载均衡功能是有问题的。原因是L7,至少如OSI模型所描述的那样,本身包含多个离散的负载均衡抽象层。例如,对于HTTP流量,请考虑以下子层:
复杂的L7负载均衡可以提供与上述每个子层相关的特征。另一些L7负载均衡器可能只有一小部分功能将其置于L7类别中。简而言之,从功能比较的角度来看,L7负载均衡器的格局要比L4类别复杂得多。(当然,本节刚刚介绍了HTTP; Redis,Kafka,MongoDB等都是受益于L7负载均衡的L7应用协议的例子)。
在本节中,我将简要总结负载均衡器提供的高级特性。并非所有负载均衡器都提供所有特性。
服务发现是负载均衡器确定可用后端集的过程。方法多种多样,一些例子包括:
运行状况检查是负载均衡器确定后端是否可用于提供流量服务的过程。健康检查通常分为两类:
/healthcheck端点的HTTP请求)向后端发送ping,并使用它来衡量运行状况。是的,负载均衡必须真正的能均衡负载!给定一组健康的后端,如何选择合适的后端来提供连接或请求?负载均衡算法是一个活跃的研究领域,范围从简单的算法,如随机选择和循环,到考虑可变延迟和后端负载的更复杂的算法。鉴于其性能和简单性,最流行的负载均衡算法之一被称“两个随机选择的力量”。
在某些应用程序中,同一会话的请求能够到达相同的后端非常重要。这可能与缓存,临时复杂构造状态等有关。会话的定义各不相同,可能包括HTTP cookie,客户端连接的属性或某些其他属性。许多L7负载均衡器对粘性会话有一些支持。稍带嘴,我要指出会话粘性本质上是脆弱的(托管会话的后端可能会宕机),所以在设计依赖它们的系统时要小心。
TLS的主题及其在边缘服务和保护”服务到服务”通信中的作用可以单独发表一篇。话虽如此,许多L7负载均衡器进行了大量的TLS处理,包括终止边界,证书验证和固定,使用SNI的证书服务等。
正如我在演讲中所说的那样:“可观察性,可观察性,可观察性。”网络本质上是不可靠的,负载均衡器通常负责导出统计数据,跟踪和日志,用来帮助运维找出问题所在,以便他们能够解决问题。负载均衡的可观察性输出差异很大。最先进的负载均衡器提供丰富的输出,包括数字统计,分布式跟踪和可自定义的日志记录。我得指出,提升的可观察性不是免费的; 负载均衡器必须做额外的工作来生产它。但是,数据的好处已经大大超过了相对较小的性能影响。
尤其是在边缘部署拓扑中(见下文),负载均衡器通常实现的各种安全功能,包括速率限制,认证和DoS缓解(例如,IP地址标记和识别,缓送等)。
负载均衡是需要可配置的。在大型部署中,这可能成为一项重大任务。通常,配置负载均衡的系统称为“控制平面”,并且实现的差异会比较大。有关此主题的更多信息,请参阅我在服务网格数据平面与控制平面上的帖子。
本节刚刚介绍了负载均衡器提供的功能类型一些表面。更多有关L7负载均衡器的部分,请参见下面的讨论。
现在我已经在高层次介绍了负载均衡器的概况,L4和L7负载均衡器之间的差异,以及负载均衡器功能的摘要,我将继续介绍部署负载均衡器的各种分布式系统拓扑。(以下每种拓扑适用于L4和L7负载均衡器)。

图4:中间代理负载均衡拓扑
图 4中所示的中间代理拓扑可能是获得大多数读者最熟悉的负载均衡方法。此类别包括Cisco,Juniper,F5等硬件设备; 亚马逊的ALB和NLB以及谷歌的云负载均衡器等云软件解决方案; 和纯软件自托管解决方案,如HAProxy,NGINX和Envoy。中间代理解决方案的好处是用户简单性。通常,用户通过DNS连接到负载均衡,无需担心其他任何问题。中间代理解决方案的一个缺点是代理(即使是集群)是单点故障以及扩展瓶颈。中间代理通常也是黑盒子,使运维变得困难。客户端是否存在问题?在物理网络中?在中间代理?在后端?这很难说。

图5:边缘代理负载均衡拓扑
边缘代理拓扑如图 5所示实际上只是中间代理拓扑的一种变体,可以通过互联网访问负载均衡器。在这种情况下,负载均衡器通常必须提供额外的“API网关”功能,例如TLS终止,速率限制,身份验证和精密的流量路由。边缘代理的优缺点与中间代理相同。需要注意的是,在面向互联网的大型分布式系统中部署专用边缘代理通常是不可避免的。客户端通常会使用服务端无法控制的任意网络库来通过DNS访问系统(使以下部分描述中的嵌入式客户端库或边车(sidecar)代理拓扑不能直接在客户端上运行)。另外,出于安全考虑,需要有一个专有网关提供所有的网络流量到内部系统。

图6:通过嵌入式客户端库进行负载均衡
为了避免中间代理拓扑中固有的单点故障和扩展问题,更复杂的基础架构已经转向通过库将负载均衡器直接嵌入到服务中,如图 6所示。库在支持的功能方面差异很大,这一类中最知名且功能最丰富的一些有Finagle,Eureka/Ribbon/Hystrix和gRPC(松散地基于称为Stubby的内部Google系统)。基于库的解决方案的主要优势在于它将负载均衡器的所有功能完全分配给每个客户端,从而消除了先前描述的单点故障和扩展问题。基于库的解决方案的主要缺点是,库必须为组织所使用的所有编程语言提供相应的实现。分布式架构正变得越来越“多语言”。在这种环境下,以多种不同语言重新实现极其复杂的网络库的成本可能会变得令人望而却步。最后,在大型服务架构中进行库升级可能会非常痛苦,因此很可能会在生产中同时运行许多不同版本的库。
尽管如此,上述的一些库已经成功地让那些能够限制编程语言扩散并克服库升级难度的公司所取得了成功。

图7:通过sidecar代理进行负载均衡
嵌入式客户端库负载均衡拓扑的另一种变体是图 7中所示的边车代理拓扑。近年来,这种拓扑结构已经被推广为“服务网格”。边车代理背后的理念是,以牺牲轻微的延迟为代价,通过iptables跳转到不同的进程,来提供对编程语言无侵入式改造的目的。在撰写本文时,最受欢迎的边车代理负载均衡有Envoy,NGINX,HAProxy和Linkerd等。有关边车代理方法的更详细的处理,请参阅我的博客文章介绍Envoy以及我的在服务网格数据平面与控制平面的博客。
总的来说,我认为sidecar代理拓扑(服务网格)正在逐步取代所有其他拓扑以进行服务到服务通信。在流量进入服务网格之前,始终需要边缘代理拓扑。
这篇文章已经讨论了L7负载均衡器对于现代协议的优势,并将在下面进一步详细介绍L7负载均衡器功能。这是否意味着L4负载均衡器不再有用?不!虽然在我看来L7负载均衡器最终将完全取代用于“服务到服务”通信的 L4负载均衡器,但L4负载均衡器在边缘仍然非常有用,因为几乎所有现代大型分布式架构都使用双层L4/L7负载均衡架构用于互联网流量。在边缘部署场景中,将L4负载均衡器置于L7负载均衡器之前的好处是:
在下面的部分中,我将介绍中/边缘代理L4负载均衡器的几种不同设计。以下设计通常不适用于客户端库和边车代理拓扑。

图8:L4终端负载均衡器
仍在使用的第一种L4负载均衡器是终端负载均衡器,如图 8所示。这与我们在上面的L4负载均衡介绍中看到的负载均衡器相同。在这种类型的负载均衡器中,使用两个离散的TCP连接:一个在客户端和负载均衡器之间,一个在负载均衡器和后端之间。
L4终端负载均衡器仍然使用有两个原因:

图9:L4直通负载均衡器
第二种L4负载均衡器是直通负载均衡器,如图 9所示。在这种类型的负载均衡器中,负载均衡器不会终止TCP连接。而是在连接跟踪(connection tracing)和网络地址转换(NAT)完成后,将每个连接的数据包转发到选定的后端。首先,让我们定义连接跟踪和NAT:
使用连接跟踪和NAT,负载均衡器可以传输从客户端到后端的大多数原始TCP流量。例如,假设客户端正在与1.2.3.4:80通信并且所选择的后端位于10.0.0.2:9000。客户端TCP数据包将到达负载均衡器1.2.3.4:80。然后,负载均衡器将交换数据包的目标IP和端口10.0.0.2:9000。它还将交换数据包的源IP和负载均衡器的IP地址。因此,当后端响应TCP连接时,数据包将先返回负载均衡器,在负载均衡器中发生连接跟踪,NAT可以反向再次发生。
为什么使用这种类型的负载均衡器代替上一节中描述的终端负载均衡器,因为它更复杂吗?一些原因如下:

图10:L4直接服务器返回(DSR)
直接服务器返回(DSR)负载均衡器如图10所示。DSR建立在上一节中描述的直通负载均衡器之上。DSR是一种优化,其中只有入口/请求数据包经过负载均衡器。出口/响应数据包在负载均衡器直接返回客户端。执行DSR有趣的主要原因是,在许多工作负载中,响应流量比请求流量大很多(例如,典型的HTTP请求/响应模式)。假设10%的流量是请求流量,90%的流量是响应流量,如果是DSR,那么使用1/10的负载均衡器容量就可以满足系统的需要。由于历史上负载均衡器非常昂贵,因此这种类型的优化会对系统成本和可靠性产生重大影响(少即是好:less is always better)。DSR负载均衡器扩展了直通负载均衡器的概念,具体如下:
请注意,在直通负载均衡器和DSR负载均衡器设计中,都有大量的途径设置连接跟踪,NAT,GRE等。不幸的是,该主题也超出了本文的范围。

图11:通过HA对和连接跟踪的L4容错
到目前为止,我们一直在考虑独立设计的L4负载均衡器。直通和DSR负载均衡器都需要在负载均衡器本身中进行一定量的连接跟踪和状态。如果负载均衡器死了怎么办?如果负载均衡器的单个实例死亡,则将切断经过负载均衡器的所有连接。根据应用的不同,这可能会对应用程序性能产生重大影响。
从历史上看,L4负载均衡器曾经是从典型供应商(Cisco,Juniper,F5等)购买的硬件设备。这些设备非常昂贵并且处理大量流量。为了避免单个负载均衡器故障切断所有连接并导致严重的应用程序中断,负载均衡器通常部署在“高可用性对儿”中,如图 11所示。典型的HA负载均衡器设置具有以下设计:
上面的设置是今天仍然有很多高流量的互联网应用在使用。但是,上述方法存在很大的缺点:

图12:通过集群负载均衡器和一致性散列的L4容错和扩展
上一节介绍了通过HA对的L4负载均衡器容错以及该设计中固有的问题。从2000年代早期到中期,大型互联网基础设施开始设计和部署新的大规模并行L4负载均衡系统,如图12所示。这些系统的目标是:
此L4负载均衡器设计被称为容错和通过群集和分布式一致性散列进行扩展。它的工作原理如下:
让我们看看上述设计如何减轻“HA对儿”方法的所有缺点:
通常被问到这个设计的一个问题是“边缘路由器为什么不通过ECMP直接与后端通信?为什么我们需要负载均衡器?“其原因主要是围绕DoS缓解和后端操作简便性。如果没有负载均衡器,每个后端都必须参与BGP,并且执行滚动部署的难度要大得多。
所有现代L4负载均衡系统都在朝着这种设计(或其某些变体)发展。最着名的两个例子是Google的Maglev和亚马逊的网络负载均衡器(NLB)。目前没有任何OSS负载均衡器可以实现这种设计,但是,我知道有一家公司计划在2018年向OSS发布一个。我对这个版本感到非常兴奋,因为现代L4负载均衡器正缺少OSS这一个至关重要的部分。

确实是的。最近几年L7负载均衡器/代理开发出现了复苏。这与分布式系统中对微服务架构的持续推动非常吻合。从根本上说,当更频繁地使用时,固有故障的网络变得更难以有效地操作。此外,自动扩展,容器调度程序等的兴起意味着在静态文件中配置静态IP的日子早已过去。系统不仅更多地利用网络,它们还变得更加动态,也需要负载均衡提供更多新的功能。在本节中,我将简要总结现代L7负载均衡器中开发最多的领域。
现代L7负载均衡器正在为许多不同的协议添加明确的支持。负载均衡器对应用流量的了解越多,它在可观察性输出,高级负载均衡和路由等方面就可以做得越精密。例如,在撰写本文时,Envoy明确对HTTP/1,HTTP/2,gRPC,Redis,MongoDB和DynamoDB支持L7协议解析和路由。未来可能会添加更多协议,包括MySQL和Kafka。
如上所述,分布式系统的日益动态的性质需要在创建动态和反应控制系统方面进行同时投入。Istio就是这种系统的一个例子。有关此主题的更多信息,请参阅我在服务网格数据平面与控制平面上的帖子。
L7负载均衡器现在通常内置支持高级负载均衡功能,如超时,重试,速率限制,熔断,阴影,缓冲,基于内容的路由等。
如上面关于一般负载均衡器功能的部分所述,正在部署的越来越动态的系统变得越来越难以调试。用健壮的协议规范可观察性输出可能是现代L7负载均衡器提供的最重要的功能。现在,任何L7负载均衡解决方案几乎都需要输出数字统计,分布式跟踪和可自定义日志记录。
现代L7负载均衡器的用户通常希望轻松扩展它们以添加自定义功能。这可以通过编写加载到负载均衡器中的可插入过滤器来完成。许多负载均衡器也支持脚本,通常是通过Lua脚本。
我写了很多关于L4负载均衡器容错的文章。L7负载均衡器容错怎么样?通常,我们将L7负载均衡器视为可消耗和无状态的。使用商用软件可以轻松地水平缩放L7负载均衡器。此外,L7负载均衡器执行的处理和状态跟踪比L4复杂得多。尝试建立基于L7负载均衡器的“高可用对儿”在技术上是可行的,但这将是一项重大任务。
总的来说,在L4和L7负载均领域中,业界正逐渐从“HA对”转向通过一致散列融合的水平可扩展系统。
L7负载均衡器正在以惊人的速度发展。有关Envoy提供的示例,请参阅Envoy的架构概述。

图13:全局负载均衡
未来负载均衡将越来越多地将各个独立负载均衡器视为商品设备。在我看来,真正的创新和商业机会都在控制平面内。图 13显示了全局负载均衡系统的示例。在这个例子中,发生了一些不同的事情:
全局负载均衡器将越来越能够完成任何单个负载均衡器无法独立完成的复杂事物。例如:
为了实现全局负载均衡,用作数据平面的负载均衡器必须具有复杂的动态配置功能。有关此主题的更多信息,请参阅我在Envoy的通用数据平面API以及服务网格数据平面与控制平面上的帖子。
到目前为止,这篇文章仅简要提到了硬件与软件,主要是在历史L4负载均衡器“HA对儿”的上下文中。这个领域的行业趋势是什么?

之前的推文是一种幽默的夸张,但仍然总结了很多趋势,它们是:
总而言之,这篇文章的主要内容是:
总的来说,我认为这是计算机网络的一个迷人时刻!大多数系统向OSS和软件的转变,正使得迭代速度提高几个数量级。此外,随着分布式系统通过“无服务器”范例继续向动态化迈进,底层网络和负载均衡系统的复杂性还将相应的增加。
原文链接:https://blog.envoyproxy.io/introduction-to-modern-network-load-balancing-and-proxying-a57f6ff80236
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3150781/ ,如需转载,请注明出处,否则将追究法律责任。