@所有运维人丨多链路负载均衡那些事儿

14000字深度好文建议先收藏再阅读

一、写在前面

企业、高校、运营商等多链路负载均衡的问题,属于老生常谈的问题,山石网科从10多年前在二级运营商打开局面,作为高吞吐、高并发、高用户数量的广域网接入设备时,就开始尝试解决多链路负载均衡的问题。

经过十多年的持续迭代和市场考验,山石网科的NGFW受到了市场广泛认可,取得了一定的成绩。即便如此,我们在最近的一些实践中,仍然发现我们的系统有优化的空间,对于有些场景和需求有更好的技术方案;于是我们在原有的基础上持续优化迭代,取得了一些阶段性的成果,特和大家进行分享。

本文中所有的内容均基于山石网科应用交付(ADC)产品(以下简称应用交付或者ADC)进行讨论,所有功能均已发布并投放市场。山石网科ADC发布于2017年末,但它并非从零开始构建,它和山石网科NGFW一样,基于山石网科多核并行分布式操作系统StoneOS进行构建。除了继承StoneOS核心软件构架、大量的网络功能以及应对高并发、高吞吐的多场景适应性之外,更重要的是继承了StoneOS的稳定性和近15年的市场考验。

二、场景描述

下图是多链路负载均衡的一个简化、抽象的拓扑,并不代表某一个行业或者客户,绝大部分场景的拓扑比下图中复杂。另外,为了简化拓扑,下图中并没有涉及HA(高可靠,High Availability)。本文着重讨论多广域网链路的流量调度,下图的拓扑虽然与真实拓扑有一些差异,但是兼具关键组件,不影响本文的讨论。下图中一些关键的元素:

运营商:ISP1、ISP2、ISP3代表三个不同的运营商。其中有三条链路接入到ISP1,两条链路接入到ISP2,一条链路接入到ISP1。实际中,用户的接入运营商数量可能比三个多,也可能少;每个运营商的链路数量也可以不同。不管有几个运营商接入,最少有两条或者两条以上的链路接入到Internet。

接入设备:本文中使用应用交付(ADC)产品作为Internet的接入设备,进行多广域网链路的流量调度。

办公区:主要包含一些访问终端,可能有PC、SIP电话、移动终端等,Internet流量主要是这些区域的终端产生的。

业务区:这里重点讨论与本文相关的DNS服务。多链路流量调度与DNS流量有着非常密切的关系(后文中会讨论)。一般的,在出口的DNS流量不会太多,但由于DNS负责将域名翻译为IP地址,也即在绝大部分的业务流量产生时,都会伴随DNS流量。合理地调度DNS查询流量,对整体的流量调度效果有着非常重大的意义。

实际中的,有的客户没有自己的DNS服务器,靠外部的运营商DNS或者公共DNS(例如电信DNS、阿里DNS等)来进行DNS解析,此时几乎所有的DNS查询都会经过Internet出口。有的客户有自己的DNS服务器,此时办公区的DNS查询中大部分会送到业务区的DNS服务器(本地DNS)进行查询,当本地DNS有权威记录或者缓存有效时,则直接返回结果,否则本地DNS进行递归或转发查询,最终从权威服务器获取到结果,并将其返回给客户端;这种情况客户端的DNS查询不经过Internet出口,本地DNS服务器到公共DNS服务器的迭代查询或者转发查询会过Internet出口。当然,即便有本地DNS服务器时,也存在一些客户端也会不使用,而使用外部DNS服务器进行查询,这种情况与没有本地DNS服务器是一样的。

三、需求分析及方案

多链路负载均衡场景的需求比较清晰,本文就出站方向(访问Internet),围绕作者在实践过程中遇到的基本需求和衍生需求展开讨论,并针对性的给出山石网科ADC的解决方案。

01 基本需求

(1)多链路接入及链路连通性探测

链路联通性探测是非常基本和常规需求,也即判断某一个Internet链路是否可以正常接入Internet,当不能正常接入Internet时(例如上游设备Down掉,运营商故障等),则不应该将流量调度到该链路上。

如何判断一个ISP链路是否可以使用,有很多种方法,例如接口状态、下一跳是否可达、远端的某个IP是否可以通过该链路可达、远端的某个服务是否可以通过该链路访问,或者通过上述方式进行加权组合最终决定链路是否可用。

链路连通性探测的问题,业界主流厂商均能很好的解决,本文不做赘述。

(2)减少跨运营商的访问

跨运营商访问的问题也很明确,由于多运营商的互联互通的问题,导致跨运营商访问相对较高的延时,甚至有些访问会不通。当然,近年来随着运营商的持续优化,跨运营商访问不能互通的问题很少发生,但是体验仍然不如在运营商内部的体验好。因此避免或者减少跨运营商的访问也是在多链路场景的一个刚性需求。

很多网站通过CDN发布自己的服务,而这些CDN遍布各个运营商或者自己构建的的各个数据中心。如下图中,www.hillstonenet.com.cn有三个IP地址,IP1属于ISP1,IP2属于ISP2,IP3属于ISP3。则当某个终端访问访问IP1时,流量调度到ISP1上一般会体验更好。

对于负载均衡设备来讲,解决跨运营商访问的问题的核心点在于有足够丰富和准确的运营商IP信息库。山石网科ADC采用合作的方式,使用被市场广泛证明的信息库。在流量调度过程中,根据目的IP地址所属的运营商,选择合适的运营商链路集合(一个运营商可能有多条链路),并在该链路集合中再使用均衡算法进行流量调度,进而减少跨运营商访问。山石网科ADC上内置IPv4/IPv6的运营商信息库,并保持持续在线更新。

实际中,跨运营商的访问可以减少到很少的比例,但是难以完全避免,主要有如下原因:

1)访问的网站并不一定有所有运营商的接入方式。例如某一个网站只有教育网接入,而客户却没有教育网接入。

2)少量IP地址没有被IP信息库覆盖到。

3)某个运营商的所有接入链路都满负荷了,新的访问即便目的地还是该运营商,也不能再往该运营商的链路上进行调度。

(3)基于AppID的调度

AppID(Application Identification,应用识别)是在10多年前被提出的NGFW的核心组件之一,也是NGFW区别于传统防火墙的核心差异之一,其背后的逻辑是“端口不等于应用”,进而推导出“基于端口的安全不等于基于应用的安全”;除此之外,AppID配合流量可视化后,用户体验大幅提升。进而AppID的理念被业界广泛接受,今天已经变成了一个非常基本的组件。

在那个用户接入处在2Mbps ADSL和二级运营占有大量接入份额的年代,广域网带宽不够,迅雷、BT、电驴、uTorrent流行,占据了大量的企业和运营商带宽,影响了Web浏览、企业电话会议等关键业务体验,给企业、高校、二级运营商造成了很大的困扰。基于AppID的流量调度、流控、安全控制大大缓解了这些问题,提高了客户的重要业务的访问体验。

回到今天,随着互联网基础设施的大幅投入,Internet接入虽然显著提升,P2P软件的使用相对10多年前有显著下降,但是Internet带宽永远都无法满足应用的需要,企业、高校和运营商对AppID的流量调度和管控仍然是刚性需求。

山石网科是国内最早实现基于AppID的流量调度和管控,并大规模部署的厂商之一;并凭借该功能在二级运营商和高校互联网出口占据绝对优势。经过十多年的迭代,当前山石网科StoneOS已经支持近5000个AppID,覆盖桌面应用、移动互联网应用、IOT应用等各个操作系统的常用应用,并保持高频率的更新和高准确率。山石网科ADC也自然地继承了这些技能。

(4)基于域名的流量调度

业界方案

基于域名的流量调度理解起来很简单,即某些网站的访问需要调度到特定的链路。这个需求主要来自于企业、政府和高校。业界中主要有如下几种方案,下面分别对这些方案进行展开说明:

1)方案一:将域名翻译为IP地址

原理:这个方案理解起来很简单,在配置流量调度策略时,将域名翻译为IP地址进行策略下发;并周期性的对域名进行解析,有变化时更新调度策略,实现起来比较简单。

下图是一个网关设备的实现示意图:当对访问www.hillstonenet.com.cn的流量配置调度策略时,数据平面像DNS模块注册(订阅)某一个域名到IP地址的映射关系;当DNS模块向外部的DNS服务器解析到IP地址或者IP地址发生变更时,将变更内容通知给数据平面。

这个方案的缺陷比较大,主要表现为如下:

缺陷一:很多网站通过CDN发布,或者有多个运营商接入,有很多个IP地址,客户端解析出来的IP地址很大概率和网关解析出来的IP地址不一致,导致下发策略不准确,最后导致对部分客户端的访问无法基于域名进行流量调度。

缺陷二:由于网关解析出来的IP经常变更,会导致频繁更新调度策略,重新构建系统的调度策略表对系统开销较大;如果某些场景还需要做会话重匹配(Session Rematch)时,则可能对系统是一个灾难性的后果,大大加剧系统瞬时负载,严重时可能由于系统负载过高而会影响正常的流量转发。

2)方案二:配合嗅探DNS流量将域名翻译为IP地址

原理:这个方案是上述方案一的基础上的演进,部分解决方案一的缺陷。此方案不通过DNS模块去解析域名,而是通过嗅探经过网关设备的DNS查询应答报文,将域名翻译为IP地址。

下图中是一个DNS A记录查询的应答报文,通过解析经过设备的DNS应答,能够将域名和IP建立映射关系。

这个方案在些场景基本可以解决网关设备和客户端对域名翻译为IP不一致的问题,但是此方案也有一定的缺陷:

缺陷一:有些场景有多个广域网接入网关,有的客户端的DNS请求根本就不经过该网关,因此无法获取到客户端的DNS流量,进而无法进行翻译。

缺陷二:实际中存在一个域名对应非常多的IP地址的情况,很多大型网站能解析出几十个或者上百个IP地址是很常见的;这就要求网关能够将这些域名对应的所有IP都记录下来,当目标网站较多时,则对系统的内存开销比会较大;当域名过多时,可能会导致由于容量不足导致的无法正确翻译的问题。

缺陷三:最关键的,仍然存在方案一的缺陷二,每当这个域名对应的IP地址变更(增加、减少),都需要重新下发和构建调度策略表。

3)方案三:将域名定义为AppID

原理:这个方案通过利用应用识别功能,将域名定义为一个新的AppID,然后通过基于AppID来进行流量调度变相解决基于域名的流量调度。

下图中是通过HTTPS访问www.hillstonenet.com.cn的TLS协商中的Client Hello,通过TLS SNI(Server Name Indication)扩展可以获取到访问的域名,可以通过这个信息做AppID的识别;HTTP的访问也类似,只是从请求头中获取相应的字段,这里不做举例。

这个方案相对方案一和方案二有显著的优势,但是在实践中最大的问题是实施会比较麻烦:

局限一:如果系统不支持自定义应用,需要发布新的AppID库来支持。这种方案基本行不通,由于客户需要进行流量调度的网站千差万别,不可能将所有的需求都加到公共的AppID库中;即便可以,交付一个新版本的AppID库需要动用研发资源,需要一天或者数天来交付,交付成本非常高。

局限二:如果系统能够支持自定义应用,由于自定义应用通常需要了解AppID引擎的语法,属于比较专业的技能,对于实施工程师和客户都是难以掌握的,用户体验也会不太好,难以大面积推广。

局限三:即便克服了局限二,由于网关设备对于TCP的流量,基本的做法都是在TCP SYN报文时建立会话,而建立会话时则需要确定出接口和下一跳,也即已经确定了该TCP连接如何调度。然而,TCP SYN报文的时候没有任何载荷信息,也即没有域名信息,无法基于内容进行识别;而只能使用目的IP和端口根据历史识别信息进行调度。进而当首次访问这个网站时,没有历史识别信息,无法识别该TCP连接的AppID,无法做出准确的调度。

当然,此方案的局限三不是一个特别严重的问题,通过牺牲首次访问,来通过目的IP/端口来记录AppID,对后续的访问做识别,还是一个相对不错的方案,实践中主要的困难还是来自于上述的局限一和局限二。

山石网科ADC的方案

说了这么多业界方案的缺陷或者局限,那山石网科ADC有什么更好的方案呢。首先,作者认为山石网科ADC的方案也并非完美的解决方案,但是此方案应该大幅优于前面的方案。

当前,随着移动互联网的高速发展,互联网流量由桌面端流量向移动端流量完成了大幅的迁移,而HTTP(HTTPS)协议也由一个应用层协议逐渐变为一个事实上的传输层协议。也就是说,非常多的应用是基于HTTP/HTTPS进行开发,而HTTP/HTTPS协议在大量的场景占据了超过50%的流量,下文中把这些基于HTTP/HTTPS的流量简称为Web流量。

基于上述的事实,既然Web流量占据了如此大的比例,而作者遇到的绝大部分的基于域名的流量调度需求也是针对Web流量。因此,山石网科ADC选择回归到需求的本质,既然是基于域名的流量调度,那么是否可能在看到域名信息之后再进行流量调度呢?

上图是网关设备转发一个HTTPS请求的流程,大致有如下几个步骤:

1)客户端发送SYN报文到www.hillstonenet.com.cn, 目的端口443

2)网关收到SYN报文后,如果没有查找到会话,走新建会话(慢路)流程,查找各种表项,根据五元组信息进行流量调度,查找到下一跳,将该SYN报文转发到下一跳;最终送达服务器。

3)服务器回应SYN/ACK,网关命中会话,转发给客户端。

4)客户端发送ACK,TCP三次握手完成。

5)TLS协商、加密数据传输…

这个做法在收到SYN报文时就进行了流量调度,看不到足够的信息。如果对上述的流程进行修改,如下图:

如上图所示,山石网科ADC通过修改常规的会话新建流程,并不在收到SYN报文时进行流量调度。对于HTTPS的流量,看到Client Hello之后,就能看到TLS扩展中的SNI(Server Name Indication),进而知道访问的域名,这样可以更加自然的进行基于域名的流量调度。

对于HTTP的Web流量,其处理的原理和HTTPS类似;只不过HTTP的流量需要通过请求中的Host字段获取到域名信息,而HTTPS的流量通过TLS Client Hello中的扩展选项SNI的Server Name字段获取到域名信息,如下:

HTTP流量:

HTTPS流量:

这个方案的难点在于要打破网关设备的常规新建会话(慢路)流程,亮点也在于此。这个方案经过实践检验,对于Web流量的基于域名的流量调度,比此前的方案明显更加自然和实用。当然,它的不完美主要体现在对于非Web流量,没有改善,仍然需要通过前面提到的AppID的方案来解决。

(5)流控

前面提到,山石网科早在10多年前以AppID + Qos进入到高校和二级运营商市场,能支持几十到十万量级客户端接入的流控。经过10多年的迭代,功能已经非常成熟,在这里不再详述。

(6)会话保持

会话保持的目的是针对一些多通道的应用,让客户端发起的多通道连接选择同样一个公网源IP与服务器建立连接。互联网上最常见的应用是游戏(为什么不提FTP,因为FTP/SIP/H323等这种常规的多通道应用,通过应用层网关(ALG)已经解决,不需要配合会话保持功能)。这些应用在与服务器建立连接时,会使用多个通道进行连接,但是应用要求多个通道的源IP必须相同,否则可能无法连通。通过会话保持保证一个客户端在一段时间内选择同一个链路,同时配合SNAT规则上的粘性来选择同样一个公网IP作为源IP,最终达到多通道选择同一个公网源IP的目的。

会话保持会优先于调度策略,也就是说一般情况下,匹配了会话保持表项之后,会先按照会话保持表中的内容选择下一跳的信息。

和业界主流厂商一样,山石网科ADC也支持多种会话保持方式,但实际中最常用的还是源 + 目的IP。

(7)链路备份

如上图中,ISP1的三条链路为最优质的链路,ISP2的链路为次优质链路,而ISP3的链路最差。而大部分情况下,ISP1的链路就足够日常使用了,ISP2和ISP3的链路可以作为备份链路,当ISP1的链路都可用时,ISP2和ISP3的链路不使用,当ISP1中有链路不可使用时再使用ISP2的链路,如果继续有链路不可用,再使用ISP3的链路。

山石网科ADC可以通过设置链路优先级,结合最小活跃链路来实现上述需求,举例如说明:

ISP1三条链路优先级为10

ISP2两条链路优先级为20

ISP3一条链路优先级为30

优先级数值越小,优先级越高。例如希望一般情况下使用ISP1的三条链路,其它作为备份链路,则可以配置最小活跃链路数量为3,则效果如下:

当ISP1的三条链路都可用时,全部使用ISP1的链路进行调度

当ISP1中有一条链路不可用后,此时活跃链路数量只有2个,不满足最小活跃链路为3的需求,系统会触发ISP2的两条优先级相同的链路同时变为可用;此时便可以有4条链路变为活跃状态。

如果ISP1中有两条链路不可用,ISP2中有一条不可用,此时ISP1和ISP2共只有两条链路可用,则会使用ISP1、ISP2、ISP3各一条链路。

通过调整各条链路的优先级和最小活跃链路数量,可以灵活实现链路备份的需求。当然,当高优先级链路恢复可用之后,仍然会先使用高优先级链路。

(8)链路繁忙保护

链路繁忙保护是为了由于某种原因(例如超大流、流量波动较大等)的情况下,如果严格按照调度算法调度时,则会恶化链路,最终导致体验不佳的问题。举几个常见的例子:

例一:例如有同一个运营商的两条链路,称之为链路一、链路二;这两条链路同样带宽,同样质量,这两条链路之间使用轮询算法调度流量。当没有会话保持时,新建的会话依次在链路一、链路二上调度。但是如果某一段时间链路一上有几条会话的流量特别大,虽然链路一和链路二上新建会话的速率几乎一样,但是由于链路一上有些流的流量特别大,导致链路一带宽利用率非常高,链路二却还闲置不少。此时如果还严格按照轮询调度,则会导调度到链路一上的访问体验非常不好。

例二:在备份链路的场景中,当所有的活跃链路都很满之后,如果仍然按照调度算法往这些链路上调度,则会导致高优先级链路非常繁忙,而低优先级链路闲置不用,最终网络体验不好。

通过配置链路的繁忙保护,可以有效避免某些链路使用率很高,而还有闲置链路的情况;当链路的利用率超过一个阈值之后,新的连接将不会往繁忙链路上调度,直至降到某阈值之下。

(9)基于时间表的流量调度策略

也即在不同时间段采取不同的流量调度策略,比较容易理解,也是比较基本的功能,这里就不多做阐述了。

(10)高速日志

会话日志也是网关位置一个比较基本溯源需求,会话日志的特点是量大,从每秒几十到每秒上几十万量级,甚至更高。

对于每秒十万量级的日志,基本很难在网关设备内部解决,一方面存储受限,另外一方面系统也不可能分配那么多的CPU算力用来处理日志。所以这种情况通常通过Syslog发送到外部专门的日志服务器处理。下图中:

左侧:左侧是比较常规的做法,数据平面的会话日志通过内部通道送给日志模块进行存储,或者由日志模块再通过Syslog协议外送到外部的日志服务器。由于数据平面通常是高速并行处理系统,会产生大量的会话日志。如果都送给日志模块统一处理,那么很明显系统的瓶颈就会在日志模块。要么日志模块无法正常服务,要么就丢日志。

右侧:右侧的方案在数据平面产生日志后,直接发给外部的日志服务器。由于数据平面是高速并行系统,直接将日志在数据平面发送到外部大大提高了日志发送的效率,其瓶颈是数据平面自己的性能瓶颈,不再有集中瓶颈点。当然,外部的日志服务器如果性能不足,也需要采用集群或者其它方式处理高速日志。

山石网科ADC同时支持上述左侧和右侧两种方式,可以通过配置来切换:

对于低速日志场景,使用左侧方案足以,可以省去外部的Syslog服务器。

对于高速日志场景,需要使用右侧方案。对于右侧方案,可以通过Syslog协议封装文本日志发送给通用的Syslog服务器;同时,也可以通过二进制的方式发送给山石网科HSA专业日志系统,可以处理更高速的日志。

(11)均衡算法

均衡算法是多链路负载均衡的核心功能之一,山石网科ADC支持非常丰富的负载均衡算法,包括目的IP哈希、源IP哈希、加权源IP哈希、源IP端口哈希、ISP算法、最小带宽、加权最小带宽、最小连接数、轮询、加权轮询、动态就近等均衡算法。上述的大部分均衡算法从字面都比较容易理解,下面主要就山石网科ADC比较有特色的一些算法进行描述。

1)ISP均衡算法

基于ISP的调度,在前面的部分也有过描述,下面主要就ISP调度的一些问题进行讨论:

问题一:前面已经讲过,ISP信息主要是通过使用目的IP在ISP信息库中进行查询;那么自然存在某些IP在ISP中无法查找到结果的情况。

问题二:当确定好ISP之后,这个ISP里面有多条链路时,又该如何在该ISP中进行均衡呢。

山石网科ADC通过引入备选均衡算法和次选均衡算法来解决上述的问题。备选算法表示当无法找查找到某个IP的ISP信息后,使用的均衡算法;次选均衡算法表示当确定ISP之后,但是这个ISP里有许多条链路时所使用的均衡算法。如下图:

2)最小带宽算法

最小带宽是实际中比较常用的算法,可以用于首选均衡算法,也常见于使用ISP做首选均衡算法,使用最小带宽均衡算法作为备选算法和次选均衡算法。

最小带宽字面意义很容易理解,就是将新建连接调度到流量(实时带宽)最小的链路上,但是工程实现时,它有如下几个问题:

问题一:如何度量实时带宽。通常的做法是统计单位时间内的总流量,再用总流量除以单位时间,从而计算出实时带宽。当单位时间太短时,比较容易出现两个单位时间的带宽差异较大,表现为带宽统计不够平滑;进一步的做法会使用几个单位时间作为滑动窗口,每次使用最近的若干个单位时间来计算这段时间内的平均带宽。

工程中,单位时间取1秒比较常见;如果使用滑动窗口的思路,可以以1秒进行总流量作为统计单位,以最近的若干个单位(例如5个单位,即5秒)计算平均带宽,这样会显得速率比较平滑。

不管采取上述的哪一种做法,统计出来的带宽都属于过去发生的事情,用过去一个周期的带宽去选择最小带宽的链路会造成什么问题呢?举例说明就清楚了:

链路一:上一周期的带宽为50Mbps

链路二:上一周期的带宽为55Mbps

链路三:上一周期的带宽为48Mbps

那么在新的一个周期里,由于上一个周期链路三的流量最小,所以新的一个周期所有流量都会调度到链路三,下一个周期也许会调度到另外一个链路上,如此往复。

很明显,这个方案最大的问题是带宽在新的度量周期内不会变更,进而导致在一个固定的周期内流量永远往一个链路上进行调度。当周期过大时,会导致流量波动很大,各个链路此起彼伏。那是否能将周期设定很小呢,前面说过,工程上很多选择1秒为度量周期;周期过小例如毫秒级时,一方面软件时钟不容易保证毫秒级的精度,另外一方面周期越短度量越容易波动,再有就是频繁的计算也对会增加计算资源开销。

问题二:调度算法其实只是流量调度中比较靠后的一环,可以认为是默认的调度策略;在调度算法前面还有会话保持、或者更优先级的调度策略,尤其是会话保持几乎都是必配项。当新的会话匹配了会话保持表之后,就不会经过调度算法进行调度,也即无法通过调度算法来调节均衡效果。

针对上述的问题,山石网科ADC借助Qos的思路,采用新的带宽度量方式。该方案能够做到在每次进行调度时,获取实时的最小带宽的链路;同时,这种方法能够将会话保持和者前置的调度规则的调度结果综合考虑进去,做到更准确的调度。

另外,一般的企业、高校接入,运营商提供的上下行链路带宽一般是一致的。但是大部分的场景,两个方向的实际流量往往不一致,一般都是下行流量大于上行流量,此时如果以上下行的总流量来进行度量,也是不合适的。对于最小带宽均衡算法,可以配置带宽度量的方向,实际部署时如果客户的下行流量远大于上行流量,则应该选择以下行流量进行带宽度量,反之选择上行流量进行度量,或者其它情况下需要选择上下行流量之和进行度量。

3)加权最小带宽

在了解最小带宽之后,加权最小带宽也就容易理解。当多条链路的链路带宽不一致时,通过权重来描述。例如链路一的链路带宽为50Mbps,链路二的链路带宽为100Mbps,那么二者的权重设置为1:2的比例即可。

4)轮询/加权轮询

轮询算法是最简单,最容易理解的算法,加权轮询在轮询的基础上只是增加了权重,这里不进行讨论。

轮询算法最大的特点是,经过其调度的会话,能够将新建会话数量绝对均衡地调度到每一个链路上。然而实际中,由于会话保持表的存在,大量的会话命中了会话保持表,不经过均衡算法来调度,最终导致无法达到轮询的预期效果。

针对这个问题,山石网科ADC通过配置“综合考虑其它调度结果”的方式,将会话保持以及其它高优先级调度策略调度的结果也参与到轮询调度的算法计算中,最终实现更加接近轮询的理论调度均衡结果。

(12)DNS流量调度

在Internet出口,一般情况下DNS的流量占比一般比较小。但是在需要基于ISP做调度的场景,DNS流量的合理调度就显得非常重要。

前面提到,ISP信息是通过目的IP从ISP信息库中查找到的,那目的IP是如何得到的呢,是通过DNS服务把域名进行翻译出来的。

现在稍微有规模的网站,就会有很多个IP地址,这些IP地址遍布在各个地区的各个数据中心,这些数据中心也会有很多运营商的接入。既然DNS服务负责从域名到IP地址的翻译,而让DNS服务器返回一个合适的IP地址,就会影响到业务流量的调度了。

如上图中,产生DNS流量的主要有两个:

内部DNS服务器产生的流量:大部分的企业、高校都有自己的DNS服务器,负责内部的域名解析。其一方面作为内部域名的权威服务器,负责内部的域名的解析;另外一方面对于外部域名的DNS查询,该DNS服务器会进行迭代查询或者转发到外部的DNS服务器进行查询。

一般情况下,由于企业/高校等使用DHCP,大部分的终端都会使用内部的DNS服务器进行域名翻译,但是也不排除一部分终端自己直接指定外部的公共DNS服务器做地址翻译。

对于上述的任意一种到Internet的DNS查询,对出口的设备都是一次调度的机会。虽然DNS流量并不多,但是后续的业务与这个DNS查询是相关联的。举例说明:

1)客户端A指定某一个公共DNS作为自己的DNS服务器,在访问www.hillstonenet.com.cn时,先发送一个DNS A记录查询到公共DNS。

2)例如应用交付将这个DNS查询从ISP1的链路送出去之后,该DNS报文的源IP被转换为ISP1链路上的某一个IP,称之为ISP1-IP1。

3)公共DNS服务器收到DNS查询,源IP为ISP1-IP1。如果公共DNS发现这个域名查询有有效的DNS缓存记录,尽可能选取一个与ISP1相同运营商IP地址返回;如果没有有效缓存,则使用一个ISP1的IP地址作为源IP进行迭代查询,例如ISP1-IP2,经过迭代查询之后,最终送到权威服务器。

4)权威服务器收到ISP1-IP2的DNS查询,此时权威服务器一般也会智能的(尽可能)返回一个ISP1的IP给公共DNS,例如ISP1-IP3作为查询结果。

5)公共DNS将ISP1-IP3作为www.hillstonenet.com.cn的查询结果返回给ISP1-IP1,最终转发给客户端。

6)客户端通过HTTPS向ISP1-IP3发起请求。

7)应用交付使用ISP调度策略,查询出该请求目的IP(ISP1-ISP3)是属于ISP1,调度到ISP1的链路上,如ISP1有多个可用链路,再使用次选均衡算法进行调度到ISP1的某一条链路上。

上述的过程是一个常规的过程,并不绝对,各个环节都依赖于公共DNS和权威DNS是智能DNS(目前的主流的公共DNS都会使用智能的调度)。从上述的过程中,可以看到在第6)步中,HTTPS业务和前面的DNS查询之间有一些关联。而应用交付可以利用这些关联性,针对DNS流量做出合理的调度,最终可以达到合理调度业务流量的目的。举例说明,例如可以针对DNS流量使用最小带宽或者加权最小带宽进行调度,这样DNS查询就会选择使用流量小的链路转发DNS查询报文,而外部DNS服务器一般也会优先返回相同ISP的IP地址作为应答,进而后续的业务流量再根据ISP进行调度时,就选择了流量比较小的链路,进而实现了对业务流量的调度。

下图是DNS查询的基本流程,上文中所说的公共DNS就是下图中的Local DNS。

(13)实际部署

上面基于单个的需求讨论了很多,实际部署过程中,由于多链路负载均衡涉及到多方面的技术,包括基于ISP的调度、基于AppID的调度、基于域名的调度、会话保持、均衡算法、DNS流量的调度以及流控。其涉及到的技术面和功能点比较多,对实施人员的要求也比较高。实际中比较容易遇到满足了ISP的调度、AppID调度、域名调度这种高优先级的调度之后,实际的均衡效果不好的问题。这里给出一些常规的部署注意事项:

1)正确配置广域网链路属性。包括上下行带宽,WAN接口属性,链路带宽在流控、链路繁忙保护会使用;正确配置广域网链路所属的ISP,基于ISP的调度需要使用;正确配置广域网链路权重,这个在一些加权算法,例如加权最小带宽、加权轮询等会使用;配置链路繁忙保护阈值,例如80%或者90%,这个需要根据实际的状态进行调整。

2)如果需要做备份链路,合理配置广域网链路的优先级和最小活跃链路数。

3)按需配置基于AppID的调度策略和基于域名的调度策略,如果需要基于AppID进行流量调度,需要开启应用识别。

4)针对DNS流量配置合适的调度算法。

5)针对其它流量按需配置首选调度算法、次选调度算法、备用调度算法和会话保持算法。

其中的第1)步属于广域网链路的属性配置,这些属性在不同的调度算法、流控中会使用;第3)步和保持算法可以理解为高优先级调度策略,比均衡算法更高优先级;其中第4)步对DNS流量的调度往往容易被忽略,但是实际对均衡效果影响较大;第5)步是对其它流量的调度,绝大部分的流量应该是在这一步调度。

实施完之后,可以通过可视化来观察流量调度效果,再根据实际的效果进行微调。

02 衍生需求

在很多多链路负载的项目实践中,除了上述的一些常见的需求之外;还遇到一些衍生需求,在这里也进行一些分享。

(1)SSL解密及流量镜像

随着互联网基础设施的越来越完善,网络安全被提到越来越重要的位置,Web流量也大量的向HTTPS进行迁移;邮件协议也越来越多的向加密迁移。

在早期NGFW、IPS、DLP上一些基于内容检测的应用层安全的功能,对于加密的流量变得不再适用。解决这个问题的最直接的方式是在合适的位置,解开加密流量,这样就可以利用企业原本构建的安全体系。

随着企业在安全上越来越多的投入,大家也意识到安全问题不是单一安全设备能够解决的,通常都需要各种安全设备协同配合,加上安全管理和安全运营,逐步提高企业的安全能力。

对于这么多安全设备,如果每个设备都需要串接在网络中,对加密流量进行解密后进行安全检测,然后再加密。且不说是不是每个安全设备有这个能力,即便都有这个能力,那串接这么多设备做解密后加密,一定会大幅增加网络延时,降低网络体验。

山石网科ADC可以将流量进行解密后,将明文的流量镜像出去,给其它网络安全设备。如下图中,山石网科ADC作为SSL代理,可以将HTTPS/POPS/IMAPS/POPS的流量进行解密(需要客户端安装证书),并将流量镜像到企业构建好的安全设施上进行安全检测:

对于镜像流量,山石网科ADC有如下特点:

1)支持将一份流量解密后,可以将明文流量复制送到多个接受端。

2)除了支持将流量镜像到直连设备之外,还可以通过IPSec/GRE隧道封装,跨二、三层网络将流量送给远端的设备。实际中GRE由于封装简单,比较常用。 

3)由于可以支持通过隧道封装进行流量镜像,因此也可以在虚拟网络进行流量镜像。

当然,这个方案由于ADC设备充当SSL中间人,需要在客户端安装证书,部署场景比较受限。常见于有强管控需求的企业或者政府;高校由于人员众多,接入比较复杂,管理也比较复杂,大规模部署难度较大。

HSCP(山石网科安全协作协议)

上面的内容提到,山石网科ADC可以将流量解密之后送给多个安全设备进行安全检测,那安全设备发现威胁之后,是否能够及时阻断呢?一般对于旁路设备的阻断有几种常见的做法:

1)对于TCP的流量,旁路部署的设备发送RST报文,尝试断开连接。这个方法优点是比较直接,发送端和接受端开销小;缺点是有可能TCP序列号对不上导致,RST被客户端和服务器端丢弃;另外这个方案只能断开当前连接,而不能做更丰富的操作。

2)旁路设备调用Restful API或者类似的方式给串联设备发送指令。这个方式好处是比较灵活,能够支持多样化的功能。缺点是开销太大,例如Restful API时,接受方需要经过驱动 -> TCP协议栈 -> 控制平面 -> 数据平面,整个过程下来,开销非常大,延时也会比较大,数据平面收到指令时攻击可能已经完成了;另外有的安全设备检测平面没有完善的TCP协议栈,或者调用系统的TCP协议栈又大大影响了数据平面的性能。这种方式难以处理高速的联动。

在上述背景下,山石网科ADC推出了HSCP(山石网科安全协作协议),这个协议就是为了山石网科ADC与其它安全设备之间进行联动协作。安全设备发现威胁后按需给ADC下发指令来关闭连接、阻断IP、阻断服务等安全策略。HSCP有如下特点:

1)高速:对于发送端,其成本与发送RST类似,延时在微妙级别。接收端直接在数据平面进行处理,不需经过要TCP协议栈和控制平面。每秒处理可以几万到几十万个协作指令。

2)简单:无状态、无协商,接受和发送方对等,不需要控制平面记录状态和协商,易集成、易扩展。

3)安全:加密、防重放、防篡改。

4)多对多:每个HSCP端点都可以若干个对端进行交互联动。

下图中是一种典型场景,当ADC将明文流量送到安全检测设备,安全检测设备发现威胁之后,可以通过HCSP下发指令让ADC断开连接、阻断IP、阻断服务等操作。

(2)正向代理

ADC产品,部署于服务器集群前面时,常使用反向代理,那什么情况下有正向代理的需求呢?实际中遇到的情况主要是将某些特定域名的流量调度到某些特定的ISP上,但是出口网关设备不具备这个能力或者不能很好的完成,而替换出口网关又是比较复杂的事情。对于这种情况,新增加一个山石网科ADC,也可以较好的解决。这个场景多见于高校。

如下图,应用交付单臂部署在交换机上,对主要的业务不影响。具体方案如下,下面举例对www.hillstonenet.com.cn流量的调度:

1)第一步,准备好ADC上的代理IP池,例如IP1 ~ IP16共16个IP。在高校内部的DNS服务器上将www.hillstonenet.com.cn解析为上述的某一个IP。这里说明一下为什么采用代理IP池,而不是单个IP。主要的原因是主流的浏览器会限制到一个目的IP的并发连接数,例如基于Chromium的浏览器(Chrome、Edge)是6个。当将很多二级域名都解析到一个代理IP上之后,对这些域名的访问的目的IP都是一个,当页面内容特别丰富,里面有许多二级域名时,会导致由于只有6个并发连接而减低页面打开速度。正常不使用这种方案时,由于许多二级域名的IP地址不尽相同,打开网站后,浏览器会向很多个IP发起连接,这样其实有许多个HTTP请求同时进行。

2)第二步,在ADC上配置对HTTP和HTTPS的代理虚拟服务器,HTTP和HTTPS的代理原理不一样,需要建立不同的代理服务器。这里简要说明一下,ADC通过HTTP服务器中的Host字段解析最终的目的IP,而HTTPS则使用TLS的SNI(Server Name Indication)扩展中的Server Name解析最终的目的IP。

3)第三步,在出口针对ADC发出的流量(源IP)进行策略路由,这个就可以解决出口网关不支持基于域名调度流量的问题。

这个方案需要DNS服务器、ADC和出口网关配合协作完成,虽然看上去有点复杂,不过逻辑比较清楚,清楚原理之后也比较容易实施。

完成上述的配置之后,举例一个终端访问www.hillstonenet.com.cn的过程。

1)第一步:客户端向内部的服务器发起www.hillstonenet.com.cn的A记录查询,DNS服务器返回IP5。

2)第二步:客户端发起HTTPS的访问,目的IP是IP5,也就是ADC设备。

3)第三步:这里面其实分为两步,ADC先解析SNI(Server Name Indication)中的Server Name,得到www.hillstonenet.com.cn,并向Internet上的公共DNS发起A记录查询,获取到www.hillstonenet.com.cn真正的IP地址Public-IP1;而后ADC向Public-IP1发起HTTPS连接,使用IP1 ~ IP16中的一个IP作为源IP,后续ADC设备在客户端和Public-IP1之间做为代理。整个过程中,ADC并不参与SSL协商,所以也不需要证书。

4)第四步:出口设备匹配策略路由,将源IP为IP1 ~ IP16的流量调度合适的出接口。

局限:实践中,这个方案也有一些局限。主要源于浏览器的连接复用机制,当打开新的页面时,浏览器会先尝试从已经建好的TCP连接池中查找,看看是否可以使用的已经建好的连接,通常需要满足如下几个条件:

1)已经建好的连接和要建立的连接目的IP和端口一样,且Scheme(HTTP/HTTPS)一样。

2)对HTTPS的访问,已经建好的TCP连接中的SSL证书可覆盖新访问的网站。

3)已经建好的连接是空闲。

当上述的条件满足之后,浏览器就会选取已经建好的的TCP连接使用,而不是重新建立一个TCP连接。

当对诸如*.hillstonenet.com.cn这种通配符域名进行代理时,其中有两个域名www.hillstonenet.com.cn和doc.hillstonenet.com.cn两个域名,其使用的证书一样,对外IP地址不一样。当使用上述的代理机制时,由于DNS可能会对www和doc两个网站返回同一个IP地址。当浏览器已经打开了www网站,再打开doc网站时,当满足了上述的连接复用条件之后,对doc.hillstonenet.com的访问就会送到www.hillstonenet.com上,最后导致错误的访问。

对于这个局限,需要将相同机构的不同精确域名通过DNS服务器解析到不同的IP上,不适合做通配符域名的代理,实际部署时需要注意。对于上述的例子,需要将www.hillstonenet.com.cn和doc.hillstonenet.com.cn解析到不同的代理IP,这样这两个网站就不会满足浏览器连接复用的要求,可以解决上述的问题。

总结

多链路负载均衡虽然是一个日常常见的场景,但是由于其涉及到许多的知识和技术点,涉及到路由、应用识别、TCP/IP协议以及DNS/HTTP/HTTPS等应用层协议,还有流控、各种调度算法、会话保持方法等概念和技术。工程上的实现,各个供应商也会有所差异,各有所长。

写本文的目的,一方面希望更多的技术人员能够了解多链路负载均衡中的一些概念和相关技术,另外也想把过去的一些经验和心得分享给大家,希望读者能有所收获。

最后,受限于作者经验、见识和理解能力,难免有些表述不够准确或者片面,还希望各位读者多多包涵、不吝赐教,谢谢!

山石网科是中国网络安全行业的技术创新领导厂商,自成立以来一直专注于网络安全领域前沿技术的创新,提供包括边界安全、云安全、数据安全、内网安全在内的网络安全产品及服务,致力于为用户提供全方位、更智能、零打扰的网络安全解决方案。

山石网科为金融、政府、运营商、互联网、教育、医疗卫生等行业累计超过20,000家用户提供高效、稳定的安全防护。山石网科在苏州、北京和美国硅谷均设有研发中心,业务已经覆盖了中国、美洲、欧洲、东南亚、中东等50多个国家和地区。(文章配图源自网络)