Sunday, December 27, 2015

集群负载均衡技术概述

集群负载均衡技术(Load Balancing)是目前互联网后端服务的关键技术,是互联网系统演化到现在这样巨大规模的基础。
客观地说,负载均衡是一个门槛相当不低的领域,已有技术主要包括硬件方案和软件方案。简单说,硬件方案性能好,但是昂贵;软件方案性能差,但是成本相对可控。
硬件方案代表为F5、Ctrix、A10、Redware 等 LB 厂商的产品,每年市场营收额高达百亿。
开源的软件实现方案也有不少,知名的包括 HAProxy、Nginx、LVS 等。
在实际大规模高性能的场景下,往往很难靠单一方案实现可靠的负载均衡服务。
很多 LB 厂家现在已经不再使用“负载均衡设备”这个术语了,改叫做应用分发(ADC、ADN)设备(甚至直接叫做 4-7 层交换机),但在这些设备中的最为基础和关键的技术仍然是对海量流量进行处理的负载均衡技术。
实际上,从客户端是否能感知或参与负载均衡的过程来区分,可以首先将负载均衡技术大概分为两大类:客户端可感知的负载均衡和客户端透明的负载均衡。当然,两类技术又可以进一步地结合起来使用。

客户端可感知负载均衡

顾名思义,客户端主动参与负载均衡过程,可以感知负载均衡存在。
典型的例子是一些客户端应用,需要动态获知服务地址。从这个意义上看,不少 P2P 应用都属于该范畴。
基本的过程可以为,客户端先向某个控制(Control)服务器发起请求,获取业务(Service)服务器地址(域名或者 IP 地址)的列表。获取列表成功后,本地按照某种均衡策略向这些业务服务器发出请求。
这样做的好处显而易见,可以降低对服务器端进行负载均衡的要求,甚至服务端可以不需要再进行负载均衡,简单资源池即可。
技术难点主要在于客户端和服务端之间的信息同步。比如业务服务器池调整后信息怎么及时更新到客户端;某些负载均衡策略需要获取实时服务器的状态信息,等等。
具体实现上,往往需要客户端和服务端进行一些配合。针对某些特定的业务场景,可以进行一些调整和优化,例如 Yahoo 就在某些互联网业务中使用了这种模式。
桌面时代的客户端往往受控性差,情况比较复杂,这种模式实现难度较大。
现在移动互联网发展起来后,客户端 APP 的可控性大大提高,比较看好这种模式的应用前景。

客户端透明负载均衡

客户端透明负载均衡实际上又包括很多层面的技术,这里都统归为一类。不同实现可能放在不同地方(运营商或者服务商等),但原理都是一致的,核心都是借用了“Overlay”的思想(计算机行业的所有问题,基本都可以通过引入新的层来实现)。
下面从客户端发出请求后的完成流程来看,可以在哪些步骤实现负载均衡。

DNS 层

首先,客户端会向某个业务服务器的域名发起请求,要先解析这个域名为具体的 IP 地址。
域名解析这块能做的事情很多,但大致上要么是运营商本地应答,要么运营商扔给服务商的域名服务器。
如果是前者(一般情况下)的话,运营商会通过本地 cache 进行查询,无命中则扔给上层域名服务或者服务商。
域名解析的过程直接决定了进行 LB 的效果。这里就有问题了,由于域名是由运营商进行维护答复的,一旦发生变化,服务商怎么去快速地调整呢,传统域名更新的方式可达数分钟甚至数小时的时延。
一种思路是跟运营商去谈,所有相关请求都服务商自己来处理或者怎么能合作进行快速更新;一种是将请求想办法绕开运营商,隧道给自己(又是一种 Overlay),腾讯的 HttpDNS 就是这个思路,域名解析不走传统 DNS 协议,而是通过 HTTP 请求来实现。
总结下,基于 DNS 的 LB 方式是比较简单直接,容易实现的,但是存在问题也不少,主要有多级 DNS 结构不可控,容易分布不均匀,和难以及时刷新等等。

IP 层

拿到 IP 之后,客户端可以发起请求到对应的 IP 地址,之后就等着接收到源地址为该 IP 的响应数据包。很自然的,可以在 LB 上替换掉这个地址,发给后端的真实服务池。这也是目前大量三层负载均衡器的基本原理。
实践中,前面挡一层 DNS 均衡,后面进行三层负载均衡,已经可以支持很大规模的场景了。
典型的,LVS 是这一类的软件方案,但具体实现上,LVS 支持三种模式:NAT(Network Address Translation)、DR(Direct Routing)、TUN(IP Tunneling)。NAT 就是把 LB 做 NAT 网关;DR 和 TUN 是想办法把流量转发给后端服务器,让后面服务器自己处理,形成三角路由。
首先,负载均衡器上会带有一个 VIP(用户看到的服务地址)和 DIP(用于探测后端服务的存活),后端真实服务器上会有 RIP。
NAT 模式下,请求和响应流量都经过负载均衡器,性能会差一些。
通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器的响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。
DR 模式下通过改写请求报文的目的 MAC 地址为某个真实服务器的 MAC(ARP 请求肯定不能自动响应了),将请求发送到真实服务器。而真实服务器将响应直接返回给客户。该模式扩展型号,但要求 LB 与真实服务器可以二层连通。这种模式因为性能好,用的很多。
TUN 是解决 DR 无法跨网络的问题,不是拿 MAC 做转发,而是封装完整包做 IP 转发,比 DR 处理要复杂。
此外,肯定要保证 Session 一致性,可以根据 IP 头和 TCP 头记录之前决策,保证流调度到同一台机器。实践中,支持十几台到数十台后端服务器比较合适。

应用层

用户访问资源需要通过 URI,一个 IP 地址上可能支持数个 URI,在三层均衡的同时,可以根据这些 URI 来制定具体的分发策略,比如访问 Front_IP:80/app1 的流量可能会被分配到 Back_IP1:80/app1;而到 Front_IP:80/app2 的流量被分配到Back_IP1:80/app2 等等。
这种应用层均衡,特点当然是最灵活,可以多级划分,但因为要看应用层的信息,计算复杂性大一些,对均衡器要求也比较高,很少有能做高性能的。