CDN 简介(三)

这个系列的文章主要参考《CDN 技术详解》,作为大陆第一本介绍 CDN 的,写的确实比较烂,根本就谈不上『详解』,但是『介绍』的性质已经达到了。因此,我会结合这本书以及自己的经验感受,皮毛的总结下 CDN 技术,因为很多具体的原体我也不是很清楚。

第 4 章 集群服务与负载均衡技术
CDN 内部的一些细节并没有一个标准来统一,所以下面说的这些也只是一家之谈,但是大的方向不会错。

CDN 是典型的负载均衡集群系统。其集群之间的通信可以分为松耦合和紧密耦合两类,其中前者有 ICP、HTCP、Cache Digest、Cache Pre-filling 等;后者以 CARP 为主。其中 CARP 相比松散的耦合有更明显的优势。
对于 LB,要解决的无非是 LB 请求的分发、会话保持、服务健康监测、故障隔离、自动恢复等问题。
分发其采取的算法基本类似,包括静态和动态两大类,静态的意思是按照预先设置好的策略进行分发,而不考虑服务器当前的实际负载状况,比较简单快捷,包括轮询、加权轮询、基于源/目的 IP 的 hash 等;动态的就是能够根据当前服务器状况进行分发,包括最小连接,加权最小连接等。
会话保持可以采取根据源 IP 地址的持续保持、cookie 持续保持等方式。
健康检测的问题,这个大部分都是从 ICMP、TCP、HTTP 层面进行检测。
目前主流的有 L4 和 L7 两种,L7 颗粒更细,但对系统的要求也比较高,因为需要针对 7 层上面的不同的协议做不同的识别分发机制,用的比较多的就是 HTTP 协议,通常使用专门的硬件实现。软件比较流行的有 LVS,Nginx,Haproxy。

第 5 章 全局负载均衡工作原理及实现
这节主要介绍 GSLB,也就是负载全部节点的调度的系统,可以使用 DNS 方式,或者基于应用层的、基于 IP 路由的方式来实现 GSLB 解析。DNS 是目前主流的商用系统的解析方式。这类产品也有硬件的实现方式,比如 F5、Radware、Cisco 等。
前面说过,目前主流的 CDN 都是通过 DNS 的方式来实现 GSLB,他的基础就是 DNS 系统。除了基本的根 DNS,TLD,以及权威 DNS,还一个非常重要的 DNS,叫 LDNS,也就是 resolv.conf 里面的 DNS,这个也是 GSLB 工作的基础。如果每个人将 DNS 设置为 8.8.8.8,CDN 就没有意义了。而通过 DNS 解析实现 GSLB 还有下面集中方式:
1. 通过 CNAME,相当于把解析权交给 CDN,然后 这个是最主流的方式,比较简单。看下面这个解析就知道了:
$ dig hdn.xnimg.cn

hdn.xnimg.cn.           418     IN      CNAME   hdn.xnimg.cn.txcdn.cn.
hdn.xnimg.cn.txcdn.cn.  207     IN      CNAME   hdn.xnimg.cn.cdngc.net.
hdn.xnimg.cn.cdngc.net. 7       IN      A       183.60.194.16
hdn.xnimg.cn.cdngc.net. 7       IN      A       183.60.194.18

2. LB 作为权威 DNS,LB 作为一个域名空间的 DNS,LB 会处理所有对这个域的 DNS 的请求。此时 LB 接管了权威 DNS 的解析工作,无论用户的请求的是否需要解析,最终都要到 LB 上,这个对 LB 的要求很高。
3. GSLB 作为 Forward DNS Proxy,也就是做个 proxy,真正的请求经过 GSLB 候到达真正的权威 DNS,然后结果返回到 GSLB,经过选择,最终返回给用户。好处就是安全性比较高,可以将真正的 DNS 部署在内网,然后就是可以比较方便的增减机器。

对于使用 DNS 解析的 GSLB,最简单的是根据 LDNS 的 IP 地址就近选择节点返回给用户,这个应该也是目前最主流的判断方式,因此,上面说的如果使用海外的 DNS,最终的结果就会变的及不可靠。除了这个,还有下面几个:
1. 服务器的健康状况,出问题的肯定要自动剔除
2. 会话保持,同一会话肯定要分配到某个机器上
3. 响应时间,不是完全准确的,只能得到一个大概的值
4. IP 地址权重,这个跟带宽资源有关

GSLB 返回给本地 DNS 的信息有两种,第一种是给出最佳的 IP 地址,其缺点是如果该 IP 突然发生故障,这就悲剧了;第二种是返回多个 IP,其中最佳的放在第一位,其缺点也比较明显,很多 LDNS 都是以轮询的方式将 IP 返回给用户,很可能返回的 IP 不是最佳的。

目前主流的 CDN 的 GSLB 都是二级架构,也就是第一层的 GSLB 用来区分不同的运营商,第二层用来具体到省市物理位置:
$ dig img.wdjimg.com
img.wdjimg.com.         583     IN      CNAME   img.wdjimg.com.wscdns.com.
img.wdjimg.com.wscdns.com. 583  IN      CNAME   1st.ecoma.glb0.lxdns.com.
1st.ecoma.glb0.lxdns.com. 6     IN      A       61.174.63.203
1st.ecoma.glb0.lxdns.com. 6     IN      A       61.174.63.204

就比如上面这个, img.wdjimg.com 被 CNAME 到了 img.wdjimg.com.wscdns.com 这个域名上,该 GSLB 根据某种规则(不一定就是根据运营商来判断)将其 CNAME 到 1st.ecoma.glb0.lxdns.com 上,然后就返回 A 记录了。

实际在实现 LB 策略的时候,需要考虑的方面比较多,大致静态跟动态。
静态的包括通过特定的用户源 IP 地址,通过加权,地理位置,简单轮询,还有个比较重要的是要考虑成本问题,这个通常跟其他的策略结合使用。由于策略相对比较简单,因此效率比较高,但是考虑到的实际情况不完全准确,负载候的最终结果依然存在失衡的情况。
动态的则根据各个节点的实时情况做调整,算法相对比较复杂,但是能够获得比较好的负载效果,不会出现长时间的节点失衡的情况。一般是将而二者结合起来使用。常用的方式有基于 POP 节点健康状况,基于会话能力的,主动测量用户的 RTT,被动测量用户的 RTT 等。主动测量就是 POP 节点主动向 LDNS 发起请求,进行 RTT 测量,但是这个做法明显比较二。被动测量则是用户给节点发送 TCP 握手的时间,不是简单的 ping。除了上面这些方式,还有基于连接数的,流量的,前者比较适合 web 服务,后者就是流媒体了。

对于 DNS 解析来说,存在 UDP flood 的可能,不过这个对于 CDN 成百 G 的带宽来说应该是小意思了。通常都有隐藏的 GSLB 在后面,在出现攻击的时候备用。

除了通过 DNS 解析来做 GSLB,还可以通过应用层来做,主要就是 HTTP,他能看到用户的 IP 地址以及请求的内容,定位颗粒更细致,当然内耗也比较大。

还有通过 IP 实现 GSLB 的。比如 LB1 跟 LB2,分别负责各自的节点的负载,然后有一样的 VIP,用户通过 DNS 解析最终向 VIP 请求,这会经过路由,有他决定走哪条路由。这个明显不能在 BGP 的跨自治域的范围实习,只能在 IGP 之类的内部自治域实行。这个需要跟运营商合作,难度比较大。

DNS 本身并不是专业做负载的。第一,如果 LDNS 跟实际的物理位置不匹配,就没有准确度可言了;第二,DNS 有缓存,如果忽略了 TTL 值,那么就会无限缓存 GSLB 之前的负载结果,等同于失效;第三,DNS 缓存无法应对突发的故障。
而 HTTP 的方式精度高于 DNS,但是也有明显的缺点。第一,GSLB 的压力很大,所有的请求都要到 GSLB 这里;第二,协议扩展比较差,这个很明显,七层的当然要分析最上层的协议了;第三,安全性相对也较差。
使用 IP 的方式,主要依靠过公网上的路由设备。但是不是真正意义上的负载均衡,还有个问题就是无法实现会话保持。

总结比较下三者的优劣。
性能上,DNS 和 IP 的方式都比较好,而 HTTP 方式全部集中到 GSLB 上请求,压力很大
准确度上,HTTP 的最高,IP 的其次,DNS 的取决于你使用的 DNS
扩展性问题,DNS 以及 IP 的都比较好,HTTP 的比较差,而且需要对各个不同的协议做定制开发
商用,DNS 使用最多,HTTP 的流媒体使用较多,IP 的没有