1、流量调度的基本流程算法
目前CDN系统流量调度是经过DNS解析来实现的,其基本原理以下图1所示。
浏览器
用户想要访问某个图片的url,分为四步:缓存
一、用户来自某个区域(如Beijing TelCom)的用户,想访问特定Url(如),应该去哪一个IP地址访问
二、TGTM根据链路信息、成本信息或节点负载信息等因素,决定让该区域的用户访问CDN 1节点
三、用户根据DNS解析返回的IP地址访问CDN 1节点,并请求该图片的内容
四、CDN1节点接收并处理用户的请求,而后将客户请求的图片返回
上面的流程是在用户的浏览器或者LDNS(Local DNS)没有对DNS解析结果进行缓存的状况下的流程,对于有缓存的系统,浏览器会从缓存中取到域名解析结果,所以流量调度策略没法影响已经缓存了DNS解析结果的用户请求,这部分请求对应的访问流量并不受调度系统的指挥,这对流量调度系统有必定的影响。服务器
2、调度目标网络
CDN系统目前承载者淘宝网大约90%的流量,全局流量调度系统须要解决的问题是如何将如此大的访问流量合理分配到分布在各地的CDN边缘节点。负载均衡
对于全局流量调度系统而言,设计目标有两个:less
(1)提高用户体验
(2)节约系统成本运维
这两个目标自己都包含不少的方面,但提取其最核心的要求,分别对应tcp
(1)下降用户访问CDN节点的延迟
(2)下降CDN节点的带宽成本ide
本文的内容就是围绕这两个目标来介绍的。
3、现有调度策略介绍
现有的CDN全局流量调度是经过商用的F5 BigIP GTM(之前称为3DNS)来实现的。F5的系统提供了Round Robin等12种局域负载均衡算法和Global Availability等15种广域负载均衡算法,其中这些负载均衡算法按照调度策略是静态配置仍是动态生成的分为静态调度方法和动态调度算法。具体的内容参考F5网站上的相关文档 F5 Networks
目前淘宝CDN系统的流量调度采用的是Topology+ratio的策略,下面对该调度策略进行具体介绍。
3.1 基本概念介绍
下面的概念摘自百科上易统整理的文档GSLB概念介绍
Classless InterDomain Routing ,是一种为解决地址耗尽,提升地址的利用效率而提出的一种措施 218.30.29.0/25 218.30.28.0/25 218.30.27.0/25 218.30.26.0/2
一组CIDR组合后的名称,主要是为了配置和检索方便 region_db user { region { name “CDN_WangSu” “FujianTelcom” “GansuTelcom” “HainanNetcom } region { name “FujianTelcom” 218.85.157.0/24 220.162.0.0/16 211.148.224.0/19 220.160.0.0/15 }
用于管理从Region到Pool之间的映射关系
topology {
// server ldns score
pool.”img01_WangSu_pool” user.”CDN_WangSu” 900
pool.”img02_WangSu_pool” user.”CDN_WangSu” 900
pool.”img03_WangSu_pool” user.”CDN_WangSu” 900
pool.”img04_WangSu_pool” user.”CDN_WangSu” 900
pool.”img01_guangdongtel_pool” user.” TB_CDN_GZ_1_MB ” 900
pool.”img02_guangdongtel_pool” user.” TB_CDN_GZ_1_MB ” 900
}
客户在使用CDN服务后将域名CNAME给CDN服务提供商的域名如imag是用户的域名,在使用CDN服务后会CNAME到imag,后者就被称为wideip
wideip {
name “img0”
pool_lbmode topology
partition “Common”
last resort
pool “img02_tel_pool”
pool “img02_southcnc_pool”
pool “img02_northcnc_pool
}
为wideip服务的一组VIP或CNAME的集合
pool {
name “img02_southcnc_pool”
ttl 300
monitor all “tcp”
preferred rr
partition “Common”
member 218.108.237.202:80
member 218.108.237.212:80
}
供Pool调度的基本元素,在CDN系统中,member用于表示一个CDN节点
member 218.108.237.202:80
Virtual IP 配置在四层交换上的公网IP和端口的组合,经过地址映射对应四层交换后一台或多台内网设备若是没有四层交换,能够借指设备上直接配置的公网IP和端口的组合与member元素相对应
3.2 基本对象之间的关系
上述基本对象的关系以下图所示
3.3 现有的流量调度方法
现有的系统工做流程是这样的:
(1)管理员根据经验预先设置好用户区域的拓扑关系,并经过设置Topology定义好为各个区域服务的Pool
(2)当一个DNS解析请求到达时,调度系统根据用户LDNS的IP地址来判断出该用户所在区域,而后根据Topology的设定找出为该区域服务的Pool
(3)当Pool中有多个member时,全部到达该pool的请求按照各个member的ratio值来进行分配。例如,系统中有3个member,其 ratio分别为100,100,200,则到达该pool的全部请求将按照25%,25%和50%的比例分配到各个member
上述策略整体上能够当作一种静态的调度策略,当系统中出现节点不可用、节点过载或者特定区域访问对应的节点延迟过大等状况时,只能等到管理员发现后对配置文件进行必定的调整以后才能解决。
4、新的流量动态调度算法
根据文中第二部分提出的调度算法设计目标,为当前系统设计了三种动态调度算法,分别是基于负载的调度算法,基于链路的调度算法和基于成本的调度算法。综合考虑链路、成本和负载的调度算法还没有进行设计和实现。
4.1 基于负载的调度算法
4.1.1 算法原理介绍
基于负载的调度算法是最先实现的一种调度算法,考虑的是在一组节点服务特定区域的用户时,用户访问这些节点的链路情况接近、节点的带宽成本也接近的前提下,如何保证访问这些节点的流量在各个节点之间按照节点的实时负载能力来分配。
举个例子来讲,假设上海地区的电信用户访问cn12和cn15的链路情况相似,cn12和cn15的带宽成本也接近,如何将上海地区电信用户的访问流量按照cn十二、cn15的实时负载能力来进行分配,以保证两个节点的负载相对于其负载能力来讲是均衡的。
基于负载的流量调度算法采用的是负反馈调度算法。负反馈是一种基于误差的调度算法,简而言之,当系统输出同指望值不相等时,控制系统根据系统输出和指望值之间的误差来对系统施加控制做用,负反馈调度算法的框图以下图所示
能够看出,系统的控制量同误差是一种负反馈的关系。
应用到基于负载的调度算法中来,当分配给某个节点的流量同其负载能力相比偏小时(误差为负),咱们应该增大分配给该节点的流量,反之,则减少分配给该节点的流量。
4.1.2 调度算法实现
基于负载的调度算法是创建在可以获取节点的服务质量(QOS)的前提下,所以如何获取节点的实时QOS是首先必须解决的一个问题。
目前CDN系统是经过部署在CDN节点内部的监控系统来获取节点的实时QOS数据。QOS数据中最重要的两项是节点的当前负载和节点的最大可用负载能力。节点的当前负载是经过统计交换机的出口流量获得的,而最大可用负载则是根据各缓存服务器的健康情况得出的。
调度系统经过监控系统提供的Web Services接口实时查询各个CDN节点的当前性能情况,而后根据负反馈调度算法生成流量分配策略。
在必定偏差范围内保持同一个pool内全部节点的ratio之和固定,记为 RATIO_SUM,
设节点i的当前流量为 cur_loadi
系统内当前的总流量为 sumi=1-n(cur_load)
并设第i个ECC节点当前的负载能力(即上述的max_usable_load)记为 max_usable_loadi,
pool内全部节点的当前负载能力之和记为 sumi=1-n(max_usable_load)
则i节点在系统内应分担的负载流量比例记为
proportioni=max_usable_loadi/sumi=1-n(max_usable_load)
按照节点的当前负载能力,节点i的指望ratio是
ratioie=RATIO_SUM*proportioni
节点i的当前指望负载应为
cur_loadie=sumi=1-n(cur_load)*proportioni
节点i的实际负载与指望负载的误差为
diffi=cur_loadi-cur_loadie
节点i当前ratio的调整值为
delta_ratioi = -P*diffi/sumi=1-n(cur_load)*RATIO_SUM
同时,为了防止流量调节过程当中各节点流量出现剧烈颠簸,设置各节点ratio的调节范围为
[(1-Th)*ratioie, (1+Th)*ratioie]
总结一下:
ratio(n+1) = ratio(n) + delta_ratioi
= ratio(n)-P*diffi/sumi=1-n(cur_load)*RATIO_SUM
= ratio(n)-P*(cur_loadi-cur_loadie)/sumi=1-n(cur_load)*RATIO_SUM
= ratio(n)-P*(cur_loadi-sumi=1-n(cur_load)*proportioni)/sumi=1-n(cur_load)*RATIO_SUM
= ratio(n)-P*(cur_loadi-sumi=1-n(cur_load)*(max_usable_loadi/sumi=1-n(max_usable_load)))/sumi=1-n(cur_load)*RATIO_SUM
if(ratio(n+1) = (1+Th)*ratioie)
{
ratio(n+1) = (1+Th)*ratioie;
}
上式中的P为负反馈比例系数,能够控制负载获得指望值的时间,P越大,(在必定偏差范围内)达到指望值的时间越短,同时系统流量的波动也越大。P过大甚至可能形成系统的不稳定。
4.2 基于链路的调度算法
4.2.1 整体介绍
基于链路的调度算法的最终目标是使得全网内各区域用户访问淘宝的延迟最小,这个问题是一个最优化的问题,实际解决起来很困难,只能随着对系统了解的不断深刻,逐步优化算法。
目前基于链路的调度算法的目标是尽可能保证用户访问淘宝的延迟在给定的阈值以内,也就是说,调度的目标是对访问延迟提供必定的保证,但并不能作到最优。
基于链路的基本思想是将链路延迟超过阈值的流量调度到链路延迟较好的链路上去,以确保全部区域的用户访问链路延迟都较好。
同基于负载的调度算法相似,基于链路的调度算法须要节点和网络的QOS数据,这里除了须要获取各个节点的当前负载、最大可用负载数据以外,还须要得到特定区域访问CDN节点的链路延迟。
各个节点的当前负载、最大可用负载等QOS数据依然是经过部署在节点内部的监控系统获取的,而各区域用户访问CDN节点的链路延迟数据则是经过淘宝的客户端链路探测工具Aliprobe的探测结果统计获得的。
目前链路探测的最主要数据有ping time和ping命令的丢包率,而区域和节点之间的链路信息则是经过综合部署在指定区域的全部Aliprobe探测客户端获取的访问指定节点的链路信息统计、综合获得的。
在基于链路的调度算法中,咱们对每个感兴趣的调度区域,根据其地理位置和系统运维经验为其指定一个默认的服务节点和一组备选的服务节点,并将这些节点组成一个pool,该pool专门为该区域的用户服务。
基于链路的调度算法必须考虑到下列异常状况:
(1)CDN节点的当前负载、最大可用负载等负载类QOS数据没法获取
(2)区域到节点的链路QOS数据没法获取
(3)节点不可用
(4)节点过载
4.2.2 算法的实现
基于链路的调度算法流程以下:
Step 1 调度周期开始,尝试获取节点的健康情况检查结果、节点类的负载类QOS数据、区域同节点之间的链路类QOS数据
Step 2 遍历全部感兴趣的区域
2.1) 将当前区域的备选节点分为如下四类:
class 1: good 节点健康、链路类QOS数据能获得而且链路延迟没有超过给定阈值、负载类QOS数据能获得、节点没有超载(全部good节点中链路延迟最小的一个节点叫作最佳备选节点)
class 2: bad 节点健康,链路类QOS数据能获得而且链路延迟超过给定阈值
class 3: unhealthy 节点不健康
class 4: other 不属于上面三类的节点
2.2) 处理区域的默认节点
2.2.1 若是默认节点不健康,则尝试将默认节点的全部流量调度到备选节点中
2.2.1.1 若是该区域有good备选节点存在,则将默认节点的流量均分到全部good备选节点
2.2.1.2 不然,报警
2.2.2 若是区域用户访问默认节点的链路不佳,则尝试将默认节点的一小部分流量(比例可配)调度到最佳备选节点中
2.2.2.1 若是该区域存在最佳备选节点,将默认节点的一小部分流量调度到该最佳备选节点
2.2.2.2 不然,报警
2.3) 处理区域的多个备选节点
2.3.1) 若是备选节点不健康
2.3.1.1) 若是默认节点能够接收更多的流量,则将不健康节点的流量都切到默认节点上,不然转下一步
2.3.1.2) 若是存在good备选节点,则将不健康节点的流量均分到good备选节点上,不然转下一步
2.3.1.3) 报警
2.3.2) 若是备选节点链路很差
2.3.2.1) 若是默认节点能够接收更多的流量,则将不健康节点流量的一部分切到默认节点上,不然转下一步
2.3.2.2) 若是存在最佳备选节点,则将不健康节点流量的一部分切到最佳备选节点上,不然转下一步
2.3.2.3) 不然,报警
2.3.3) 若是默认节点可以接受更多的流量
2.3.3.1) 若是存在good备选节点,则将全部good备选节点的部分流量切回默认节点
2.3.3.2) 若是存在other备选节点,则将全部other备选节点的部分流量切回默认节点
Step 3 遍历全部过载节点
对于每个过载节点,首先报警,而后找出其所服务区域中全部不以该节点为默认节点的区域,尝试将区域流量的一部分切回区域对应的默认节点。若是找不到不以该节点为默认节点的区域,则报警
Step 4 开始新一轮的调度,转Step 1
其中, Step 2中根据链路延迟进行调度的流程以下图所示:
4.2.3 算法存在的问题
目前系统没法得知某一区域用户的访问流量值,因此在本调度算法中将区域访问流量在节点之间调度时的具体流量值是没法获得的,为了防止调度过程当中流量出现大的波动,每一个调度周期调度的流量都会很小,但调度幅度小必然致使调度效果显现的时间会比较长。
另外,目前基于链路的调度算法中会有一个比较关键的阈值(最大延迟,超过该阈值会认为链路差,不然认为链路好),该阈值是经过经验设置的,但实际上这个值在不一样的时间段,不一样的网络情况下应该是不一样的,而且应该随着时间的变化而变化,该阈值的设置仍有较大的改进空间。
4.3 基于成本的调度算法
4.3.1 CDN节点的带宽成本模型
CDN的带宽成本能够分红保底带宽和流量成本两部分。其中保底带宽指的是只要使用该节点就必须支付的费用,而流量成本指的是在保底带宽之上,按照实际使用的流量来支付费用。节点的带宽成本模型以下图所示:
4.3.2 算法设计和实现
基于成本的调度算法的目标是使得系统的带宽成本最小,这里采用的贪婪算法来实现流量的调度
算法简述以下:
(1)若是系统当前总的流量小于全部节点的保底带宽之和,则将流量按照各节点的保底带宽占全部保底带宽之和的比来分配流量
(2)若是系统当前流量大于全部节点的保底带宽之和,则首先将全部节点的保底带宽使用满,而后依次选取各节点中带宽成本最低的节点,将该节点的负载能力用完为止。
算法流程以下图所示:
在实际实现时,因为调度过程当中流量有可能出现波动,因此必须保证出现波动时不会出现问题。举例来讲,若是某一节点的保底带宽是1G,若是分配给该节点 的流量就是1G,但因为流量出现波动,就会出现除了须要支付保底带宽费用以外,还须要支付一部分超出保底带宽的费用,这是咱们所不但愿看到的。所以,咱们 在处理保底带宽和阶梯价格上限时留有必定的裕量。