最近我注意到,对现在网络均衡和代理的解释性材料非常缺乏。我心想:怎么会这样子?负载均衡是构建可靠的分布式系统的核心概念之一。这里肯定有一些有质量的可用信息了吗?我尝试去搜,发现的确十分少。维基百科上关于负载均衡和代理服务包括了一些观点的概述,但不是这个主题的一系列更新的内容,特别地当在现代微服务架构下时。Google搜到的负载均衡的结果吧,主要跳转去一些充满流行词却没有细节的供应商页面。

本文试图通过仔细介绍现代网络均衡和代理,以减少相关信息的缺乏。坦率讲这是一个巨大的话题,甚至可以是一本书来讲。为了让此文保持博客长短,我试着将一组复杂主题提炼成一个简单的概述。根据兴趣和反馈,我会考虑在晚些时候以单独的文章来表达更多的细节。

带着这些个为啥写这个的原因,我们开始吧。

什么是负载均衡和代理

维基百科定义了负载均衡是:

在计算上,负载均衡改进了多个计算资源之间的工作负载分布,比如计算机,计算集群,网络连接,cpu,磁盘。负载均衡的目标,是优化资源使用,最大化吞吐量,最小化响应时间,并避免任何单个资源的资源过载。使用多个有负载均衡的组件来代替单个组件,可以通过冗余来增加可用性和可靠性。负载均衡通常涉及专门的软件或硬件,比如多层交换机或者DNS服务进程。

上面的定义适用于所有方面的计算,不只是网络。操作系统用负载均衡来跨物理处理器调度任务,像k8s的容器编排使用负载均衡来跨计算机集群调度任务,网络调度均衡器使用负载均衡来跨可用的后端调度网络。本文的内容将只讲的是网络负载均衡。

图1 网络负载均衡预览

图1 网络负载均衡预览

图1显示了high level的网络负载均衡预览。一系列客户端向一系列的服务器请求资源。负载均衡器从high level层面设置在客户端和后台之间,其中执行几个关键任务有:

在分布式系统中正确使用负载均衡能带来许多好处:

负载均衡器 vs 代理

当谈到网络负载均衡器的时候,负载均衡器和代理这两个词经常在业内可以粗略交换一下。本文也将延续这一传统。(学术上来讲,并不是所有的代理都是负载均衡器,但大多数的代理的主要功能都在扮演负载均衡器)

另外一些人可能认为,当负载均衡作为一个内置客户端库的一部分完成后,就不是一个真正的代理了。尽量如此,我想要表达为了区分一个已经令人困惑的话题又添加了不必要的复杂性。下面详细讨论负载均衡器拓扑的类型,但本文将嵌入式负载均衡器拓扑视为代理的特例,应用程序通过内置库进行代理,该内置库提供了与应用程序进程外的负载均衡器相同的抽象。

L4(连接/会话)负载均衡

今天当讨论行业的负载均衡时,解决方案通常被分为两类:L4和L7。这类别是OSI模型里的四层和七层。由于各种原因,当讨论7层负载均衡时会变得无趣,我想对于我们提到的这些术语来说这是不幸的。OSI模型对于 负载均衡解决方案的复杂度来讲,是非常不理想的,包括传统4层协议如TCP和UDP,但通常最终会在各种不同OSI层里放一些协议。比如一个4层的负载均衡器,也支持TLS终端,那现在是7层负载均衡器了吗?

图2 4层终端负载均衡

图2 4层终端负载均衡

图2显示了传统的4层TCP负载均衡器。此案例中,客户端建立了tcp连接到负载均衡器。负载均衡器结束了连接(即直接回了SYN),选择一个后端,建立一个新的tcp连接到后台(发一个新的SYN)。图表的细节不重要,而且会在后面专注4层负载均衡的章节里来说细节。

本节的关键是4层负载均衡器通常只在L4 TCP / UDP连接/会话级别运行。因为,负载均衡器大致来回地混合字节,并确保来自同一会话的字节在后端有相同的内容。4层负载均衡器并不理解任何字节被打乱的应用细节。字节可能是http,redids,mongodb,或者其他任何应用协议。

7层应用负载均衡

4层负载均衡很简单常见。从7层应用负载均衡来看,4层负载均衡有什么毛病?以以下的4层具体案例为例:

在过去的方案里,后端选择处理A负载将会比B低大约3000倍!这是个大问题,这首先会破坏负载均衡的目的。注意这也会发生在任何多路复用、保活协议中。(多路复用是指在一个4层连接上并发发出应用请求,保活是指当没有活跃请求时不关闭连接)。由于效率的原因,所有现代协议都在发展为多路复用和保活状态(创建连接通常很昂贵,特别是在使用TLS加密连接时),因此L4负载均衡器阻抗不匹配随着时间的推移变得更加明显。这个问题在7层负载均衡器上被修复了。

图3 HTTP2 7层终端负载均衡

图3 HTTP2 7层终端负载均衡

图3显示了一个7层http 2负载均衡器。此例中,客户端发起一个单独的http2 tcp连接到负载均衡器。负载均衡器接着搞2个后端连接出来。当客户端发2个http2的流给负载均衡器时,流1给后端1,流2给后端2。因此,即使多路复用又在请求负载上具有巨大差异的客户端,也可以在后端高效地进行均衡。 这就是为什么L7负载平衡对于现代协议如此重要的原因。(L7负载均衡由于能够检查应用程序流量而产生了巨大的额外优势,下面会详细介绍。)

7层负载均衡和OSI模型

如前在4层负载均衡上所述,使用OSI模型来描述负载均衡功能是有问题的。原因在于L7至少如OSI模型所述,本身包含多个离散的负载平衡抽象层。例如,http流量要考虑下面的子层:

一个复杂的7层负载均衡器会提供上述所有子层的相关功能。一般的7层只会有一些在7层上协议的子集。简言之,7层负载均衡器从功能角度来讲要比4层更加的复杂。(而且当然本节只是讲到了http。redis kafka mongodb等等都是7层应用协议可通过7层负载均衡得到好处的例子)。

负载均衡功能

本节我将简短总结负载均衡器提供的high level的功能。并不是所有的负载均衡器都会提供这些功能。

服务发现

服务发现是负载均衡器用来决定一组可用后端的过程。方法比较多样,其中一些包括:

健康检测

健康检测是负载均衡器用来决定后端是否可以接流量的过程。健康检测通常分为两类:

负载均衡

是的,均衡器的的确确是在均衡压力。给出一组健康的后端,如何选择他们来服务连接或者请求?负载均衡算法是一个活跃的研究领域,算法范围从简单如随机选择和轮循,到复杂到考虑可变延迟和后端负载。最流行均衡算法之一给出了它的性能和简易性,在《2次最少请求请求负载均衡的力量》文中有介绍。

会话保持

在某些应用程序中,相同会话的请求打到相同的后端很重要。这种可能不得不靠缓存、临时构造复杂的结构等办法来搞。会话的定义很多,包括http cookies、客户连接的属性、或者其他什么特征。许多7层均衡器在会话保持上能够支持一部分。另外我注意到会话保持是一件天生易出问题的事(接会话的后端有可能会挂掉),所以如果一个系统设计成依赖他们的话一定要小心。

TLS终端

在TLS话题及边缘服务和安全的服务间通讯这点上,值得写一篇单独的文章。说到这里,许多7层均衡器搞了大量的TLS处理,包括终端、证书验证和固定,用SNI做证书服务等。

可观测性

就像我在演讲里说的:“可观测,可观测,可观测。”网络是天然不可靠的,均衡器要经常在统计导出、追踪、帮助管理员指出哪里坏了的日志上给反馈,以便让他们能解决问题。负载均衡器在可观测性上相差很大。大多数高级负载均衡器提供了丰富的输出,包括数字统计、分布式追踪、定制化日志。我想指出的是,增强可观测性并不是免费的,负载均衡器不得不做额外工作来达到。尽管如此,数据的好处大大超出了相对较小的性能影响。

安全和DoS减缓

尤其是在边缘部署拓扑(见下),负载均衡器经常实现了很多功能,包括限速、授权、DoS减缓(例如,ip地址标记、识别、缓发等等)。

配置和控制界面

负载均衡器需要可配置。在大的部署上,这可以变成一个重大的任务。一般来说,配置负载均衡器的系统被称为控制界面,实现差别巨大。此话题更多信息请见我另一篇关于服务网格的数据和控制面板。https://medium.com/@mattklein123/service-mesh-data-plane-vs-control-plane-2774e720f7fc

更多

本节只是刚刚触及负载均衡口碑提供的各种功能的表面。更多讨论在下面的7层负载均衡器章节。

负载均衡器拓扑类型

目前为止我已经聊到了high level的什么是负载均衡器,4层和7层负载均衡器的区别,负载均衡器功能摘要等概览,我将继续介绍多种多样的负载均衡器在分布式系统中的拓扑。(下面每种拓扑都可以在4层和7层均衡器中可用。)

中间层代理

图4 中间层代理负载均衡拓扑

图4 中间层代理负载均衡拓扑

图4显示为中间层代理拓扑,对大多数读者来讲这很可能是获得负载均衡最常见的方式。分为来自思科、juniper、F5等的硬件设备,如亚马逊的ALB、NLB和谷歌的云负载均衡器等的云软件解决方案,纯软件自host的解决方案有haproxy、nginx、envoy等。中间层代理的方案好坏是用户简单。通常,用户通过DNS连接到均衡器,不用关心其他东西。中间层代理不好的是地方是,事实上代理(甚至是集群化后)是一个单点的故障点,会成为扩展的瓶颈。中间层代理也常常是黑盒,导致管理员操作困难。在客户端是不不是有观测到问题?问题是在物理网络?在中间层代理?后端?很难说清楚。

边缘代理

图5 边缘代理负载均衡拓扑

图5 边缘代理负载均衡拓扑

图5显示的边缘代理其实是中间层代理拓扑的一种变种,负载均衡器直接通过互联网访问负载均衡器。在这种情况下,负载均衡器通常必须提供额外的API网关特性,比如TLS终端、限速、授权、复杂流量路由。这和中间层代理的好坏处都一样。一个警告是,在大型面向互联网的分布式系统中,典型的不可避免的要专门部署边缘代理。客户端典型地需要用不受服务拥有者控制的各种网络库,靠dns访问系统(内置客户端库或者下文里提到的边车代理拓扑不可能在客户端直接实现)。另外,出于安全原因,需要一个单独的网关,将所有面向互联网的流量导入到系统中来。

内置客户端库

图6 通过客户端库做负载均衡

图6 通过客户端库做负载均衡

为了避免在中间层代理拓扑中与生俱来的单点故障和扩展问题,更复杂的基础设施已经将负载均衡器直接通过一个库内置到服务中,如图6所示。这些库在支持的能力上差异巨大,但我们知道的大多数拥有丰富功能的有:finagle,eureka,ribbon,hystix,grpc(松散的基于谷歌内部一个叫做Stubby的系统)。基于库的好处是它能完整将所有均衡器的功能都分给所有的客户端,所以也能避开前面提到的单点故障和扩展问题。基于库的坏处主要是实际上必须为组织里所有的语言栈都要提供库。分布式架构变得多语言化。在这种环境下,在各种语言栈重新实现一个非常先进的网络库的成本可能会被禁止。最终,给一个大型服务架构里部署库更新时将极度痛苦,所以极有可能许多不同版本库将会并在在生产环境中,增加了操作复杂度。

如前所述,前面说的库已经成功限制于编程语言栈的扩散和克服库升级的痛苦。

边车代理

图7 通过边车代理做负载均衡

图7 通过边车代理做负载均衡

内置客户端库代理的变种均衡拓扑是边车代理拓扑,如图7。最近这些年,这种拓扑被以服务网格所普及。边车代理背后的想法是,因为要跳到不同的进程上去,在成本上有一点轻微费一点响应时长,几乎可以得到内置库所有的好处,且没有语言栈锁定。到写本文时,最流行的边车代理负载均衡器有envoy、ngx、haproxy、likerd。更多的详细边车代理的细节请见我的博客文章:https://eng.lyft.com/announcing-envoy-c-l7-proxy-and-communication-bus-92520b6c8191 https://medium.com/@mattklein123/service-mesh-data-plane-vs-control-plane-2774e720f7fc

不同负载均衡拓扑摘要和优劣

总体来讲,我觉得边车代理拓扑(服务网格)将渐渐取代其他服务间通讯的拓扑。在流量进入服务网格时,边缘代理拓扑将一直被优先需要。

4层负载均衡艺术的当前状态

4层负载均衡器是否依旧有用?

本文已经讨论了7层负载均衡器在现代协议下如何强大,再往后面的内容我们再转过来讲7层负载均衡器功能。是不是说4层负载均衡器不再有用了?不!尽管我觉得7层均衡器在服务间通讯上最终将完整取代4层,4层均衡器在边缘上依旧非常有用,因为几乎所有的现代大型分布式架构都使用了4和7的双层负载均衡架构来挡互联网流量。在边缘部署上将4层放在7层前面的好处有:

在后面的章节我会描述一下中间层和边缘代理在4层上的不同的设计。接下来的设计一般不能做成客户端库或者边车代理拓扑。

TCP/UDP终端负载均衡器

图8 4层终端负载均衡器

图8 4层终端负载均衡器

第一类仍在使用的4层负载均衡器是图8显示的终端负载均衡器。这和上面我们讲过的4层负载均衡是一样的均衡器。此类有两个独立的tcp连接被使用:一个在客户端和均衡器之间,另一个在均衡器和后端之间。

4层终端负载均衡器因为两个原因仍在使用:

1.他们相当容易实现。

2.低延时的接近用户的连接终端有巨大的性能影响。特别地,如果一个终端的负载均衡器,可放到接近使用弱网络(比如手机网)用户的地方,在将数据转移到可靠的光纤传输途中直至其最终位置之前,重发可能会更快地发生。换句话说,这样的均衡器应该被用于tcp连接终端的入网点接入。

TCP/UDP透传负载均衡器

图9 4层透传负载均衡器

图9 4层透传负载均衡器

第二类4层负载均衡器是图9显示的透传负载均衡器。此类中,tcp连接不结束在均衡器。取而代之的是,每个连接的数据包,都透传给在连接跟踪和NAT后选中的后端。首先,让我们来定义连接跟踪和NAT:

使用连接跟踪或NAT,均衡器都能从客户端到后端转发主要的原始tcp流量。比如,假设客户端向1.2.3.4:80通讯,然后选择的后端是10.0.0.2:9000。客户端tcp包发到1.2.3.4:80的均衡器。均衡器将能缓存起来10.0.0.2:9000的包里的目标ip和端口。同样,也缓存了带了均衡器ip地址的数据包的源ip。因此,当后端回应tcp连接时,数据包会回到均衡器,此处进行连接跟踪,NAT能够在相反方面重新演一遍。

为什么会使用这种类型的负载均衡器来代替上一节中描述的终端负载均衡器,因为它比较复杂?

一点原因:

直接服务转发(DSR)

图10 4层直接服务转发(DSR)

图10 4层直接服务转发(DSR)

DRS负载均衡器如图10所示。DRS建立在前面的小节提到的透传负载均衡器之上。DSR是一种只能入口、请求数据可穿过负载均衡器的优化。出口和响应的数据绕开均衡器直接回复给客户端。这么有趣地搞DSR的主要原因是在众多的工作量中,响应流量使请求流量显得更小(例如,典型的http请求和响应模型)。假设10%是请求流量,那90%会是响应流量。如果DSR被使用,那只要十分之一的能力就可满足系统要求。历史上负载均衡器都极其贵,这种类型的优化可以在系统成本和可靠性上产生很大的影响(成本都是越低越好)。DSR负载均衡器扩展了透传性负载均衡器如下的一些点:

注意不管是透传还是DSR的设计,有大量的方法做网络跟踪,NAT,GRE等,他们都会存在于负载均衡器和后端之间。不幸的是,这超出了本文的讨论。

通过高可用的双机做容错

图11 通过HA对和连接跟踪做4层容错

图11 通过HA对和连接跟踪做4层容错

目前为止,我们一直在隔离地考虑4层负载均衡器的设计。不管是透传还是DSR,都要求在负载均衡器本身记录一部分连接跟踪和状态。那如果负载均衡器挂了呢?如果一个单实例的负载均衡器挂了,所有的经过的连接都会断掉。取决于应用,可能会对其性能产生重大影响。

历史上,4层负载均衡器一般都是从典型的供应商买的硬件设备(思科、juniper、F5等)。这些设备极其贵,也能处理海量的流量。为了避免一个单点的负载均衡器失败切断了所有连接,导致大量应用停摆,负载均衡器典型地被部署在如图11显示的高可用对的形式下。一个典型的HA负载均衡器配置如下设计:

上述设置仍然是今天海量互联网应用之选。但上述方法存在很大的不足:

通过分布式一致性哈希搞容错和扩展

图12 通过集群负载均衡器和一致性哈希做4层容错和扩展

图12 通过集群负载均衡器和一致性哈希做4层容错和扩展

上一节介绍了通过HA对做4层负载均衡器容错以及该设计中固有的问题。从21世纪初到中期,大型互联网基础设施开始设计,如图12所示的新的大规模并行4层负载均衡系统被部署。这些系统的目标是:

这种4层负载均衡器设计最好描述为容错、并通过集群和分布式一致性哈希进行扩展。它的工作原理如下:

让我们看看上述设计如何缓解HA对方法的所有缺点:

有关这种设计的典型问题是“为什么边缘路由器不通过ECMP直接与后端对话?为什么我们需要负载均衡器?“其原因主要在于减少DoS和后端操作的简化。 如果没有负载均衡器,每个后端都必须参与BGP,并且执行滚动部署的时间将更加困难。

所有现代化的4层负载均衡系统都在朝着这种设计方向发展(或其一些变体)。最着名的两个例子是Google的Maglev和亚马逊的网络负载均衡器(NLB)。 目前还没有实现这种设计的OSS负载均衡器,但是,我知道有一家公司计划在2018年将其中一个发布到OSS。我对此版本感到非常兴奋,因为现代4层负载均衡器是一个至关重要的部分,在网络空间中缺少OSS。

7层负载均衡艺术的当前状态

技术上的代理战争目前完全是字面上的代理战争。或“代理之战”。Nginx plus,HAProxy,linkerd,Envoy都会毫不夸张地杀死它。而代理即服务/路由即服务SaaS供应商也在不断提高业务水平。非常有趣的时刻!

@copyconstruct

确实是的。最近几年,7层负载均衡器/代理开发领域出现了复苏。随着分布式系统中微服务架构的不断推进,这种情况非常好。从根本上讲,当被更频繁使用时,天生有缺陷的网络变得更加难以运维。 此外,自动扩展,容器调度等的出现意味着静态文件中静态IP的配置日期早已不复存在。系统不仅更多地利用网络,而且它们变得更加动态,更加需要负载均衡器中的新功能。 在本节中,我将简要概述在现代7层负载均衡器中发展最为迅速的领域。

协议支持

现代7层负载均衡器为许多不同的协议添加了明确的支持。 负载均衡器对应用程序流量的了解越多,就可观察性输出、高级负载均衡和路由等方面而言,它可以做的更复杂的事情。例如,在撰写本文时,Envoy明确支持L7协议解析和路由用于HTTP / 1,HTTP2,gRPC,Redis,MongoDB和DynamoDB。未来可能会增加更多的协议,包括MySQL和Kafka。

动态配置

如上所述,分布式系统日益动态的特性需要并行投入来创建动态和反应式控制系统。Istio就是这样一个系统的一个例子。有关此主题的更多信息,请参阅我在服务网格数据与控制面板上的文章。

高级负载均衡

7层负载均衡器现在通常内置对高级负载均衡功能的支持,例如超时,重试,速率限制,断路,投影,缓冲,基于内容的路由等。

可观测

如上面有关常规负载均衡器功能的小节所述,正在部署的日益动态的系统越来越难以调试。鲁棒的协议指定可观测性输出可能是现代7层负载均衡器提供的最重要的特性。 任何7层负载均衡解决方案现在都需要输出数字统计信息、分布式跟踪和可自定义日志记录。

扩展性

现代7层负载均衡器的用户通常希望轻松扩展它们来添加自定义功能。这可以通过编写加载到负载均衡器的可插入过滤器来完成。许多负载均衡器也支持脚本,通常通过Lua脚本。

容错

关于4层均衡器容错上面我写了一些。7层怎么容错?一般地,我们认为7层负载均衡器是可挂的和无状态的。使用商业软件可7层负载均衡器轻松地水平扩展。此外,7层执行的处理和状态跟踪要比4层复杂得多。试图建立一个7层的HA对在技术上可行的,但这将是一项重大的任务。

总体而言,在4层和7层领域,业界正从HA对转向水平可扩展系统,这些系统通过一致性哈希组织。

更多

7层负载均衡器正在以惊人的速度发展。有关Envoy提供的示例,请参阅Envoy的架构概述。

全局负载均衡和中央控制界面

图13 全局负载均衡

图13 全局负载均衡

负载均衡的未来将越来越多地将单个负载均衡器视为商品设备。在我看来,真正的创新和商业机会都在控制层面。图13显示了一个全局负载均衡系统的例子。在这个例子中,几个不同的事情正在发生:

全局负载均衡器将越来越能够完成复杂任务,而不需要单独的负载均衡器。 例如:

从硬件到软件的进化

到目前为止,这篇文章只是简单地提到了硬件和软件,主要是在历史4层负载均衡器HA对的背景下。这方面的行业趋势是什么?

我已经看到了八层软件的新OSI堆栈。我认为它更像这样:

@infosecdad

以前的推文是一个幽默的夸张,但仍然相当好的趋势,这是:

负载均衡的未来和讨论

总结一下,这篇文章的主要内容是:

总的来说,我认为这是一个计算机网络的迷人时刻!对大多数系统而言,采用OSS和软件的做法正在将迭代速度提高数个数量级。此外,随着分布式系统通过“无服务器”范式继续向动态发展,底层网络和负载均衡系统的复杂性也将需要相应地增加。

translated from https://blog.envoyproxy.io/introduction-to-modern-network-load-balancing-and-proxying-a57f6ff80236

54chen 注:真nm长。。。