现代网络负载均衡和代理 0
Jun 2, 2023 23:30 · 2862 words · 6 minute read
原文:https://blog.envoyproxy.io/introduction-to-modern-network-load-balancing-and-proxying-a57f6ff80236
什么是网络负载均衡器和代理?
图 1 从高层次上展示了负载均衡:一些客户端从一些后端请求资源,中间的负载均衡器扮演了关键角色:
- 服务发现:系统中哪些后端可用?它们的地址是什么(负载均衡器如何能够联系上它们)?
- 健康检查:哪些后端是健康的,可以正常接收请求?
- 负载均衡:用哪种算法来均衡请求至健康的后端?
在分布式系统中正确地使用负载均衡可以带来这些好处:
- 命名抽象化:客户端无需知道每个后端(服务发现),只要能找到负载均衡器就行了,名称解析委托给负载均衡器。找到负载均衡器的方法包括内置库和众所周知的 DNS/IP,下面将详细讨论。
- 容错:通过健康检查和各种算法,负载均衡器可以有效地绕开不良或超载的后端。这意味着运维通常可以气定神闲地修复问题而不是火急火燎。
- 开销和性能优势:分布式系统的网络可能跨越多个网络区域。在同一区域内,网络带宽的开销相对小,而不同区域之间,开销通常超配。智能负载均衡尽可能将请求流量保持在各个区域内,提高性能(更低的延迟)并降低整体系统开销(更小的带宽和更少的光纤)。
负载均衡器 VS 代理
当谈到网络负载均衡器时,业内通常将负载均衡器和代理两个术语混用。本文也把它们看作等同。(严格来说,并非所有代理都是负载均衡器,但绝大多数代理都有负载均衡功能。)
有人可能认为,当负载均衡器嵌入客户端时,这样的负载均衡器并不是真正的代理。但是我认为这种区别给本就已经让人困惑的话题增加了不必要的复杂性。下文将详述负载均衡器的拓扑类型,但是将嵌入式的负载均衡器视为代理的一种特殊情况;应用程序通过提供与
四层(连接/会话)负载均衡
如今在讨论负载均衡时,解决方案通常分为两类:L4(四层)和 L7(七层),来自 OSI 模型。该模型是用于负载均衡解决方案是不妥当的,其中包括了传统的四层协议(TCP 和 UDP),还有不同 OSI 层上的协议片段。例如,如果四层 TCP 负载均衡器也支持 TLS 终结,那它算七层负载均衡器吗?
图 2 是一个传统的四层 TCP 负载均衡器。在该案例中,客户端与负载均衡器建立 TCP 连接,负载均衡器终结连接(直接应答 SYN),选择一个后端,并与之建立一个新的 TCP 连接。细节并不重要,将在下面详细讨论。
关键在于四层负载均衡器通常只在 L4 TCP/UDP 连接/会话上运行。因此负载均衡器将字节来回搬运,并确保同一会话的字节最终到达同相同的后端。四层负载均衡器不知道它在搬运的字节详细的应用层信息,这些字节可以是 HTTP、Redis、MongoDB 或任何其他应用层协议。
七层(应用程序)负载均衡
四层负载均衡简单易用,且被广泛使用。那么它的缺点是什么,以至于需要这套七层(应用层)负载均衡?来看几个四层的特定案例:
- 两个 gRPC/HTTP2 客户端通过一个负载均衡器来连接后端。
- 四层负载均衡器分别为每个入向的 TCP 连接创建一个单独的出向 TCP 连接,这样就有两个入向和出向的连接。
- 但是客户端 A 通过它的连接每分钟发送一个请求(RPM),而客户端 B 每秒发送 50 个请求(RPS)。
在上述场景中,服务客户端 B 的后端的负载大约是服务客户端 A 的后端的 3000 倍!这是个大问题,这就不是负载均衡了。注意任何多路复用(multiplexing)、保持连接(keep-alive)的协议都有可能出现这个问题。(多路复用是指通过单个四层连接并发发送应用程序请求;保持连接意味着在没有请求活动时不关闭连接)所有现代协议处于效率考量都在演变成多路复用和保持连接(通常创建连接的开销很大,尤其是当使用 TLS 加密时),因此四层负载均衡器的阻抗不匹配问题随着时间的推移愈加明显。这个问题可以通过七层负载均衡器来解决。
图 3 是一个七层 HTTP/2 负载均衡器。在这里案例中,客户端与负载均衡器建立单个 HTTP/2 TCP 连接。负载均衡器建立两个后端连接。当客户端向负载均衡器发送两条 HTTP/2 流,流 1 被发往后端 1;流 2 被发往后端 2。因此请求负载不同的多路复用客户端也会被有效地均衡负载。这就是为什么七层负载均衡对现代协议非常重要。(因为具有检查应用程序流量的能力,七层负载均衡好处多多,下面将详说)。
七层负载均衡和 OSI 模型
如上所述,使用 OSI 模型描述负载均衡特性是有问题的,是因为七层本身包含了多个离散的负载均衡抽象层。以 HTTP 为例:
- 可选的 TLS,大家对 TLS 属于 OSI 哪一层争论不休
- 物理 HTTP 协议(HTTP/1 or HTTP/2)
- 逻辑 HTTP 协议(header、body)
- 消息协议(gRPC、REST)
一款负载的七层负载均衡器能够提供与上面子层相关的功能,但有些可能只有其中一小部分功能。总之,从功能角度来看七层负载均衡器要比四层复杂得多。(当然除 HTTP 外还有 Redis、Kafka、MongoDB 等应用层协议)
负载均衡器功能
并非所有负载均衡器都完整地提供这些功能。
服务发现
服务发现是负载均衡器确定可用后端集合的过程。方法多种多样:
健康检查
健康检查是负载均衡器确定后端服务是否可用于承载流量的过程。通常分为两类:
- 主动:负载均衡器定时发送 ping(例如向 /healthcheck 路径发送 HTTP 请求)到后端,并以此来评估其健康状况。
- 被动:负载均衡器从主数据流中探测健康状态。例如,四层负载均衡器可能会在连续三次连接错误后判断后端不健康;而七层负载均衡器则可能在连续三个 HTTP 503 后判断后端不健康。
负载均衡
负载均衡器必须均衡负载!在一组健康的后端中如何选择服务用于连接或请求?负载均衡算法是个活跃的研究领域,从随机选择和轮询等简单算法到考虑变量延迟和后端负载等复杂算法。2次幂最小请求数负载平衡是最受欢迎的算法之一,因其性能和简洁被广泛使用。
会话黏连
在某些应用程序中,同一个会话中的请求到达同一个后端非常重要。这可能与缓存、临时状态有关。会话的定义因情况而异,可能包括 HTTP cookie、客户端连接属性或其他属性。许多七层负载均衡器都支持会话黏连。顺便说一句,会话黏连是脆弱的(应答会话的后端可能会挂掉),因此在设计依赖它的系统时需要谨慎。
TLS 终结
TLS 话题及其在通信安全中的作用值得单开一篇来探讨。话虽如此,许多七层负载均衡器支持大量 TLS 处理,包括终结、证书验证和使用 SNI 提供证书等。
可观测
网络本质上是不可靠的,而负载均衡器通常负责导出统计数据、追踪和日志,来帮助运维人员找出问题所在并修复。各种负载均衡器在可观测输出方面差异很大,最先进的负载均衡器提供了丰富的输出,包括数据统计、分布式追踪和可定制化日志。我要指出增强型可观测性会带来额外的开销,但数据带来的好处远超较小的性能影响。
安全和 DoS 缓解
尤其在边缘的部署拓扑中,负载均衡器通常实现包括限速、认证和 DoS 缓解(例如 IP 地址标记和识别)等各种安全功能。
配置和控制平面
负载均衡器需要被配置。通常,配置负载均衡器的系统被称为“控制平面”,其实现方式各不相同。有关该主题的更多信息请查看服务网格数据平面 vs. 控制平面。
更多
本文仅对负载均衡器的功能浅尝辄止,更深入的讨论请详见下篇。