负载均衡小结

本文是对这篇介绍负载均衡(Load Balancing)的博客的笔记。

负载均衡指在分布的计算资源中尽可能合理地分配任务/请求,比如操作系统调度处理器,Kubernetes管理集群,以及代理分发网络请求,都使用到负载均衡的技术。但本文只讨论网络请求的负载均衡。为简单起见,我们把负载均衡器叫做代理(proxy)。

分类

可以根据网络OSI模型将代理分为L4和L7两种类型。L4代理按照第四层传输层数据(TCP、UDP)分发请求;L7代理根据应用层的内容(HTTP,Redis,MongoDB等)分发网络请求。

L4代理能够确保来自同一条连接的所有数据包,会被转发到同一台后端服务器。当网络请求到达时,L4代理选择一台可用的后端服务器并转发。一种转发方式是L4代理终止来自客户端的连接,使用新连接把请求转发到后端服务器。另一种方式类似NAT,L4代理对数据包的报头进行地址替换,使得数据包直达后端服务器。如果在第二种方式的基础进一步通用路由封装(Generic Routing Encapsulation, GRE),则可以实现直接服务器返回(Direct Server Retur),减轻代理的压力。

与L7代理比较,L4代理的缺点在于基于连接分发请求,可能存在负载不平衡的问题。比如A和B客户端分别建立一条TCP长连接来发送HTTP2请求,分别被代理转发到两个后端服务器。其中A以每秒1个数据包的速度发送请求,B的速度是每秒1000个数据包,导致两台后端服务器承受不同压力,而L4代理无法分析应用层的数据来改善负载分布。但由于结构简单,L4代理的吞吐量更高,可以用于防御DDos(比如SYN Flood)。

功能

代理除了均衡负载,还可以用于服务发现(Service Discovery),健康检查(Health Checking),容错(Fault Tolerance)和命名抽象(Naming Abstraction)。

代理维护一个可用后端服务器的列表,这个过程称为服务发现。常用的实现方法有:静态文件配置,DNS,Zoopkeeper等。代理通过健康检查确定后端服务器是否可用。健康检查有主动和被动两种类型:主动的代理向后端服务器发送周期性心跳信号;被动的代理通过数据流判断后端服务器的健康状况,比如L4代理通过TCP连接状态,L7代理通过HTTP状态码(503服务不可用)。基于健康检查,代理可以进一步实现容错机制,重启宕机的服务。命名抽象指代理为客户端提供统一的入口,客户端不需要知道后端服务器的具体地址与端口。

除此之外,代理还常常提供粘性会话(Sticky Session),TLS终止(TLS Termination),和可观察性(Observability)等特点。

常见拓扑结构

负载均衡有中间代理(Middle Proxy),边缘代理(Edge Proxy),作为客户端依赖库(Embedded Client Library),和内部通讯(Sidecar Proxy)等4种常见拓扑结构。

  • 中间代理:这是最简单的代理拓扑结构。只需要配置DNS,就可以令客户端连接到中间代理。这种拓扑的缺点是代理是单点错误。

  • 边缘代理:相比较中间代理,额外起网关的作用。其余功能与中间代理完全相同,所以也存在单点错误的缺点。

  • 作为客户端依赖库:解决了单点错误的问题。但如果客户端用多种语言开发,那么必须为每一种语言都提供相应的负载均衡库。

  • 内部通讯:在客户端运行单独的进程用作负载均衡。目前最推荐采用的拓扑结构。

尾声

博客后文还提到负载均衡的其他方面,比如L4代理利用BGP协议实现容错等。关于L7代理,作者提到全局的负载均衡器和中心化的控制面板的体系,用于调控运行在客户端的代理分发策略,是未来创新和趋势的所在。