在互联网时代的早期,网站流量还相对较小,业务也相对简单, 单台服务器便可满足访问需要,但时至今日,互联网应用也好,企业 级应用也好,一般实际用于生产的系统,几乎都离不开集群部署。信 息系统不论是单体架构多副本还是微服务架构,不论是为了实现高可 用还是为了获得高性能,都需要利用多台机器来扩展服务能力,希望 用户的请求不管连接到哪台机器上,都能得到相同的处理。另一方 面,如何构建和调度服务集群这件事,又必须对用户保持足够的透 明,即使请求背后是由一千台、一万台机器来共同响应的,也无须用 户关心,他们只需要记住一个域名地址即可。调度后方的多台机器, 以统一的接口对外提供服务,承担此职责的技术组件被称为“负载均 衡”(Load Balancing)。
真正大型系统的负载均衡过程往往是多级的。譬如,在各地建有 多个机房,或机房有不同网络链路入口的大型互联网站,会从DNS解析 开始,通过“域名”→“CNAME”→“负载调度服务”→“就近的数据 中心入口”的路径,先将来访地用户根据IP地址(或者其他条件)分 配到一个合适的数据中心中,然后才到各式负载均衡。在DNS层面的负 载均衡与前面介绍的DNS智能线路、内容分发网络等在工作原理上是类 似的,差别只是数据中心能提供的不只是缓存,而是全方位的服务能 力。由于这种方式此前已经详细讲解过,后续我们所讨论的“负载均 衡”就只聚焦于网络请求进入数据中心入口之后的其他级次的负载均 衡。
无论在网关内部建立了多少级的负载均衡,从形式上来说都可以 分为两种:四层负载均衡和七层负载均衡。在详细介绍它们是什么以 及如何工作之前,我们先来建立两个总体的、概念性的印象。
- 四层负载均衡的优势是性能高,七层负载均衡的优势是功能 强。
- 做多级混合负载均衡,通常应是低层负载均衡在前,高层负载 均衡在后
我们所说的“四层”“七层”指的是经典的OSI七层模型中的第四 层传输层和第七层应用层。
应用层负载均衡
前面介绍的四层负载均衡工作模式都属于“转发”,即直接将承 载着TCP报文的底层数据格式(IP数据包或以太网帧)转发到真实服务 器上,此时客户端与响应请求的真实服务器维持着同一条TCP通道。但 工作在四层之后的负载均衡模式就无法再转发了,只能代理,此时真 实服务器、负载均衡器、客户端三者之间由两条独立的TCP通道来维持 通信。
“代理”这个词,根据“哪一方能感知到”的原则,可以分为 “正向代理”“反向代理”和“透明代理”三类。
- 正向代理就是我们 通常简称的代理,指在客户端设置的,代表客户端与服务器通信的代 理服务,它是客户端可知,而对服务器透明的。
- 反向代理是指在服务 器侧设置的,代表真实服务器与客户端通信的代理服务,此时它对客 户端来说是透明的。
- 透明代理是指对双方都透明的,配置在网络 中间设备上的代理服务,譬如,架设在路由器上的透明翻墙代理。
根据以上定义,很显然,七层负载均衡器属于反向代理的一种。 如果只论网络性能,七层负载均衡器肯定比不过四层负载均衡器,它 比四层负载均衡器至少多一轮TCP握手,有着跟NAT转发模式一样的带 宽问题,而且通常要耗费更多的CPU,因为可用的解析规则远比四层丰 富。所以如果用七层负载均衡器去做下载站、视频站这种流量应用是 不合适的,起码不能作为第一级均衡器。但是,如果网站的性能瓶颈 不是网络性能,而是整个服务集群对外所体现出来的服务性能,那么 七层负载均衡器就有它的用武之地了。因为七层负载均衡器工作在应 用层,可以感知应用层通信的具体内容,往往能够做出更明智的决 策,玩出更多的花样。 举个生活中的例子,四层负载均衡器就像银行的自助排号机,转 发效率高且不知疲倦,每一个到达银行的客户根据排号机的顺序,选 择对应的窗口接受服务;而七层负载均衡器就像银行大堂经理,他会 先确认客户需要办理的业务,再安排排号。对于理财、存取款等业 务,大堂经理会根据银行内部资源进行统一协调处理,以加快客户业 务办理流程;而对于无须柜台办理的业务,大堂经理会直接自行处 理。回到七层负载均衡器中,反向代理能够实现静态资源缓存,所以 对于静态资源的请求,反向代理会直接返回,而无须转发到真实服务 器。
均衡策略与实现
负载均衡的两大职责是“选择谁来处理用户请求”和“将用户请 求转发过去”。前面我们仅介绍了后者,即请求的转发或代理过程。 前者是指均衡器所采取的均衡策略,由于这一块涉及的均衡算法太 多,笔者无法逐一展开,所以本节仅从功能和应用的角度去介绍一些 常见的均衡策略。
- 轮询均衡(Round Robin):每一次来自网络的请求轮流分配给 内部的服务器,从1至N然后重新开始。此种均衡算法适合于服务器集 群中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡 的情况。
- 权重轮询均衡(Weighted Round Robin):根据服务器的不同处 理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的 服务请求。譬如:设置服务器A的权值为1,B的权值为3,C的权值为 6,则服务器A、B、C将分别接收到10%、30%、60%的服务请求。此 种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的 服务器负载过重。
- 随机均衡(Random):把来自客户端的请求随机分配给内部的 多个服务器,在数据量足够大的场景下能达到相对均衡的分布。
- 权重随机均衡(Weighted Random):此种均衡算法类似于权重 轮询算法,不过在分配处理请求时是随机选择的过程。
- 一致性哈希均衡(Consistency Hash):将请求中的某些数据 (可以是MAC、IP地址,也可以是更上层协议中的某些参数信息)作 为特征值来计算需要落在的节点,算法一般会保证同一个特征值每次 都一定落在相同的服务器上。这里的一致性是指保证当服务集群某个 真实服务器出现故障时,只影响该服务器的哈希值,而不会导致整个 服务器集群的哈希键值重新分布。
- 响应速度均衡(Response Time):负载均衡设备对内部各服务 器发出一个探测请求(例如Ping),然后根据内部各服务器对探测请 求的最快响应时间来决定哪一台服务器响应客户端的服务请求。此种 均衡算法能较好地反映服务器的当前运行状态,但最快响应时间仅仅 指的是负载均衡设备与服务器之间的最快响应时间,而不是客户端与 服务器之间的最快响应时间。
- 最少连接数均衡(Least Connection):客户端的每一次请求服 务在服务器停留的时间可能会有较大差异,随着工作时间增加,如果 采用简单的轮询或随机均衡算法,每一台服务器上的连接进程可能会 产生极大的不平衡,并不能达到真正的负载均衡。最少连接数均衡算 法会对内部需负载的每一台服务器有一个数据记录,记录当前该服务 器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分 配给连接数最少的服务器,使均衡更加符合实际情况,使负载更加均 衡。此种均衡策略适合长时处理的请求服务,如FTP传输。
从实现角度来看,负载均衡器的实现分为“软件均衡器”和“硬 件均衡器”两类。在软件均衡器方面,又分为直接建设在操作系统内 核的均衡器和应用程序形式的均衡器两种。前者的代表是LVS(Linux Virtual Server),后者的代表有Nginx、HAProxy、KeepAlived等。 前者性能会更好,因为无须在内核空间和应用空间中来回复制数据 包;而后者的优势是选择广泛,使用方便,功能不受限于内核版本。