调度系统是指CDN厂家有能力通过各种机制将客户域名的所有现网请求引导到合适的目标机房,从而实现流量控制、质量控制、成本控制以及故障处理。
一般有哪些调度形式?
在介绍这些调度方式前,我们来看看客户是怎么接入CDN的,或者说客户如何把流量切往CDN,我们假设客户的域名叫www.test.com,大概只有这么几种方式:
这是最常见的方式,即CDN厂家向客户提供一个调度域名,客户将自己业务域名的CNAME指向这个调度域名,从而实现将请求引导到CDN上来。比如腾讯云向客户提供的CDN是 $domain.cdn.dnsv1com ,所以客户的域名 www.test.com 如果需要将请求切到腾讯云CDN上,只需要将 www.test.com 的CNAME 设置为 www.test.com.cdn.dnsv1.com 即可。
CNAME方式的背后,又分几种:
a) 一种是CDN厂家提供基于DNS的调度,就最终客户的域名经CDN的调度域名解析出CDN节点的IP。腾讯云CDN就是这种玩法,大家可以dig p200107.ping.dnsv1.com看下效果。 对应前面的调度方式1。
b) 一种是CDN厂家给的CNAME实际不是真正CDN节点,而是一个调度集群,真正的CDN IP地址是通过在调度集群上向请求响应302跳转实现的。 对应前面的调度方式2。
c) 再有一种,是Anycast CDN。从DNS层面上看,CDN厂家提供给你的CNAME的解析结果只有全球固定的一两个IP地址,不像方式1中不同地区的解析结果IP不同。这种场景下的流量调度, 不是靠DNS解析,而是Anycast BGP路由的调整,通过调整Anycast的路由来调度各地区的流量到哪个机房。对应前面的调度方式3。
这种模式也比较奇葩,主要是一些想代理商客户(比如创世云),即想用腾讯云CDN来接他们自己的客户,又不想在DNS层面暴露他们用了腾讯云。 一般做法是客户提供一个自己的域名比如gslb.mycdn.com,腾讯云也提供一个中性的且不备案的平台调度域名glsb.mycdn-platform.com。真正的客户域名 www.test.com CNAME到 gslb.mycdn.com ,后者CNAME到腾讯云的调度域名 gslb.mycdn-platform.com。这样整个解析环节都没有腾讯云的痕迹。这里属于调度方式1。
这种方式不太觉见,我只知道 cloudflare 这一家。再是 www.test.com 为例,如果客户要将请求切往CDN,需要将 test.com 的NS记录改为 cloudflare 提供的NS 权威服务器。Cloudflare相当于同时担当了DNS服务商和CDN服务商的角色。这里本质上还是属于调度方式1。
第一种基于local DNS的调度是怎么实现的?
CDN的调度服务器本身就是调度域名的NS权威服务器,调度域名的TTL被故意设置成很短(比如3分钟),这样所有请求都会较频繁地触发客户端的local DNS重新到CDN调度服务器解析新的IP地址。此时CDN的调度服务器依据是local DNS的出口地址。
调度流程如下:
A. 客户端DNS TTL过期无首次访问,向local DNS发起DNS查询
B. local DNS在递归解析过程中,向CDN的调度服务器发起解析请求;
C. CDN调度服务器可以看到local DNS的出口ip(有时还有基于EDNS的客户端ip);
D. 通过IP库获取上一步IP的地理及运营商属性,从当前调度域名的策略规则中去匹配,同时结合其它的因素(比如质量监控、机房成本因素等)得到最佳的一组IP;
下面通过实际例子来说明整个过程:
场景:
访问URL | http://p73.ping.dnsv1.com/a.php | . |
---|---|---|
测试机出口IP | 113.87.117.154 (中国 广东 深圳 电信 中国电信) | 出口IP会变化,但大概率稳定在深圳电信。 |
DNS服务器 | 202.96.134.133 、202.96.128.166 (中国 广东 深圳 电信 中国电信) | 中国电信DHCP自动配置 |
DNS出口地址 | 202.96.136.240 (中国 广东 深圳 电信) | 多次测试结果会发生变化,但大概率稳定在深圳电信 |
目标域名解析 | p73.ping.dnsv1.com 的DNS解析情况如下:-> p73.ping.dnsv1.com.cdn.dnsv1.com-> 388957.p23.tc.cdntip.com-> 113.96.154.108 等十多个IP |
基于local DNS的方法有哪些优点:
简单易用、用户无感知
客户端兼容性好
基于DNS的调度有哪些缺点?
调度策略非实时生效
DNS是树型分布式系统,所有节点上都会按域名的TTL来做缓存,这就导致CDN的调度策略其实并不是实时生效的,比如有个IP(或VIP)故障,将它从现网完全隔离需要一定的时间,比如510分钟。3分钟调到秒级,但又会遇到新的问题:
这个问题可通过将CDN调度域名的DNS TTL调小,比如由1
》一般运营商的DNS服务器出于安全考虑,会忽略太小的TTL值强制改为固定值;
》假设运营商老老实实按你的极短的秒级TTL来,也会导致较频繁触发DNS解析;
DNS解析是有成本的,当客户端自身网络或CDN的DNS权威网络或服务性能太差时,将非常明显地增加业务的请求延迟,这对冷域名请求量较小的业务又是响应时间敏感型业务影响非常大。
如果TTL太长呢,导致CDN的调度策略变化后全网生效时间过长,如果CDN某个机房故障需要从现网调度剔除,DNS全球生效如果要花上30分钟,那这30分钟内访问到原故障IP的请求就都仍旧是失败的。
调度不够精确
大量的local DNS不支持edns协议,拿不到客户的真实IP,CDN绝大多数时候只能通过local DNS ip来做决策,而local DNS ip有时候不太靠谱。常常遇到的问题有:
》客户配置了非本地区的DNS服务器,比如深圳电信用户配置了北京电信的DNS服务器,结果CDN给你分配了北方的CDN节点IP;
》DNS服务器的出口IP与入口IP差距大,比如某些小运营商的DNS服务器IP看起来是本地的,但实际DNS流量绕大半个中国从另外的区域出去,所以也会导致CDN给出完全不对的节点IP;
》上一种类型,还有一种情况,像8.8.8.8这种Public DNS,接入IP是Anycast IP没有归属地一说,出口IP经常变动,比如中国大陆使用时,出口IP经常是中国台湾的google 机房。DNSPOD所说有针对这种情况做特殊处理,凡是google中国台湾来的请求强制判断为中国大陆。
第二类基于302跳转的调度如何实现?
先看下这种模式下与前面的DNS调度有什么不同。
仍以访问 http://p73.ping.dnsv1.com/a.php 为例。 在DNS解析调度模式下,浏览器访问上面的URL时,正常情况下会收到CDN节点的返回码200和文件内容,即DNS解析到的IP会直接做为文件服务器响应浏览器请求。类似于:
HTTP/1.1 200 OK
Server: NWS_S1
Connection: keep-alive
Date: Sun, 11 Dec 2018 19:44:02 GMT
Transfer-Encoding: chunked
Keep-Alive: timeout=120
X-Daa-Tunnel: hop_count=2
X-NWS-LOG-UUID: 750246221628030518 0be2170ce2df3d9f634cd70470120401
\r\r\r\n文件内容
但在302跳转模式下,上述URL的访问,浏览会收到一个状态码为302的响应
HTTP/1.1 302 Moved Temporarily
Server: stgw/1.3.6.2_1.13.5
Date: Sun, 16 Dec 2018 19:38:58 GMT
Content-Type: text/html
Content-Length: 168
Connection: keep-alive
Location: http://61.142.166.245/p73.ping.dnsv1.com/a.php
意思是告诉浏览器,你需要继续访问Location中的URL去请求实际的文件内容。所以浏览器又发起了第2次请求:
http://61.142.166.245/p73.ping.dnsv1.com/a.php
这个URL中的IP地址,就是CDN调度系统为我们分配的CDN节点,我们来看这个IP是怎么拿到的。
域名解析的过程和基于DNS的调度一样,最终都会拿到一组IP。目标IP有两种情况:
》一种情况是,目标IP并不是CDN的实际边缘节点,而是302调度集群的IP;
》还有一种可能是这些IP就是CDN的普通边缘节点IP;
浏览器向第一次拿到的IP发起http请求;
如果这个IP实际上是CDN的边缘节点,它会从本机的配置文件中读取信息 p73.ping.dnsv1.com这个域名的请求Host如果不是IP,URL形式为:http://p73.ping.dnsv1.com/a.php 则将请求转发到后端调度集群;
若请求Host为IP,对应的URL形式为: http://61.142.166.245/p73.ping.dnsv1.com/a.php 则读取缓存提供文件服务。
此时请求到了调度群集上,我们能拿到的客户端信息有 客户端的出口IP(绝大多情况下是相同的),接下来算法和基于DNS的调度可以是一样的,只是判断依据由local DNS出口ip变成了客户端的出口IP;
调度集群毕竟不是CDN节点,无法向客户端提供实际的文件内容,此时它只能通过302报文告知客户端,你可以去上一步骤计算的IP请求文件;
浏览器收到302回应,跟随Location中的URL,继续发起http请求,这次请求的目标IP是CDN边缘节点,且Host是IP,CDN节点会响应实际的文件内容;
基于302跳转的调度有何优点:
实时调度
由于每次拿到的最终IP都是实时计算的结果,所以调度策略是实时生效的,不像基于DNS的调度会受到DNS TTL缓存的影响而有延迟。
实时调度有什么好处?
》可以快速隔离故障设备;
》可以精确控制节点与机房的带宽和资源负载;
》可以快速对应业务的突发,特殊适合大文件下载类突发场景,比如手机固件、游戏安装包、大体积资源的分发;
准确性高
由于可以拿到请求的出口IP,在不考虑NAT或小运营商出口飘移这种奇葩场景时,客户端归属地更贴近真实情况,不受用户的DNS配置影响,配错了也没关系;
但是也有限制:
业务兼容性
要求客户业务的客户端必须支持302跟随,比如手机固定或应用下载,如果下载客户端不识别http 302响应码,那下载就会失败。
对延时敏感业务不适用
这种模式的调度,每个请求都会多出一次http交互。比如web静态小资源就不太合适,一个网站加载几十个js/css文件,每个文件都302跳转一次?那加载时间会成倍增加。
所以302只适用于客户端兼容性好的大文件下载业务。
第三类基于Anycast BGP路由的调度如何实现?
这种模式在表现形式上和第一种DNS调度一样:
业务域名通过CNAME解析到CDN的调度域名;
CDN的调度域名解析出的IP即边缘节点IP,请求不会发生302跳转;
但也有特殊之处:
解析结果的全球IP数量极少,通常只有12个,或者一个大洲或大片区域12个;
DNS的TTL通常极大,经常配置成2小时甚至更长;
Anycast路由技术使得物理分布在全球/全球不同区域的不同服务器具有相同的IP地址,客户端对这个IP的请求会在路由层面引导到最近的物理服务器上。Anycast CDN我们后续单独用一篇文章讲解,这里先略过实现细节。
Anycast CDN的优点:
由于IP少且固定,TTL长,对CDN权威服务器的DNS解析性能要求不高;
在路由层面完成了就近接入CDN,比DNS抗干扰,比302兼容性好;
路由策略变动生效时间快,优于DNS调度;
受DDOS攻击时,只需调整路由,将攻击流量引导到高带宽清洗机房,无需从现网剔除IP;
Anycast CDN的缺点:
由于腾讯云CDN不是Anycast方式,以下缺点并不一定合理。
方案复杂
全球网络复杂,BGP路由的优化相当繁琐,稍不小心后果就是网络不通,或请求绕地球一周延时高出天际;
成本高
Anycast实施需要整个完整的IP C段,IP浪费严重,为达到好的效果和扛攻击,全球机房都要有足够的带宽;
可能大家会怀疑Anycast CDN可用性会不会有问题,一个TCP会话的多个数据包会不会因为路由多播造成前后发往不同的机房而导致传输失败。 这个问题已经有前人研究过了,并且现在国际大厂cloudflare、verizon(edgecast)、highwinds都跑在Anycast模式下,应该已经不是大问题了。
Linkedin有篇文章详细描述了这个问题,可以做为参考:
https://engineering.linkedin.com/network-performance/tcp-over-ip-anycast-pipe-dream-or-reality