此文是根据马涛在【QCon高可用架构群】中的分享内容整理而成,转发请注明出处。

马涛,前迅雷网络CDN系统研发工程师,也曾任EMC/Pivotal大数据处理系统Hawq研发工程师。从事CDN之前主要做数据库内核,平时关注大数据处理、并行系统容错和优化、后台服务性能优化。

1.CDN系统工作原理

1.1 DNS解析方式

客户网站使用CDN加速应用或其他下载类资源:

客户域名: example.com

客户加速域名: cdn.example.com

CDN 厂商加速域名: cdn.com

CDN 厂商 CNAME 域名: example.com.cdn.com

 

上图是不使用CDN加速的情况。解析DNS是由客户的权威服务器完成的。要使用CDN加速,客户需要在自己的权威 dns 中配置:cdn.example.com => example.com.cdn.com,然后用户只需要将需要加速的文件挂上cdn.example.com就可以自动使用CDN系统加速了。

用户请求客户页面的流程如下:

www.example.com => 解析返回客户 http server ip

页面中嵌入的 cdn.example.com => 解析返回 CDN 的域名 example.com.cdn.com => 经过 CDN 厂商 + DNS 调度后, 返回指向某个特定的 IP(这个过程可能经历了多次 CNAME 跳转)。

用户通过建立 http 连接, 请求服务器下载资源。

下面的图,是加入了CDN系统的请求流程,因为中间加入了CNAME跳转,在客户端就可以无缝同时访问多个服务器展示信息。

 

优点:

  • 最通用的方法
  • 最简单的方法

缺点:

  • 功能限制: 只能根据域名解析 ip 地址, 不能进行额外的优化
  • 容易被影响: 不遵守 DNS 解析 TTL 的代理服务器, DNS一些常见的劫持问题

这是传统的CDN加速方式,也是市面上最常见的方式。优缺点很明显,这里我就简单列举出来。

1.2 非DNS解析方式

客户通过嵌入SDK, 不经过传统 DNS 解析方式来使用 CDN 资源. 例如:HttpDns。
客户在自己的程序中嵌入一个查询模块,任何查询域名的操作都经过该模块代理完成。协议可以是自定义的, 加密可以单独控制, 查询的内容也可以定制化。刚好周一分享过 HttpDns Lib 的内容(可关注本公众号,查看历史文章),我这里也就一笔带过了。

优点:

  • 功能强大: 可以根据资源, 甚至其他信息来允许调度程序进行额外的优化工作
  • 传输协议灵活: 可以是标准的自定义 tcp/udp 协议, 也可以是 http 协议
  • 不容易被影响: 报文可以加密, 协议为自定义协议, 不容易被劫持和缓存

缺点:

  • 不兼容传统协议
  • 很多客户程序不兼容, 例如: 浏览器, 第三方应用
  • 需要额外实现解析的服务程序

目前很多视频播放软件都是采用第二种方案进行,因为这种方案可以对资源进行准确定位,提高资源命中率。
对大家来说,CDN系统是一个比较透明的系统,这也是为什么很多人可能不知道CDN系统的原因。那么下面,我来简单介绍下,CDN厂商自己的CDN系统架构。

1.3 CDN 系统架构

上是China Cache分享的架构图,大部分 CDN 系统在组成上没有本质区别。但是组成的方式,模块间的交互设计影响着各个功能的实时性/可靠性/可扩展性。

运营系统模块

主要包含元数据,和一些最外层的控制展现。客户需要简单的访问一些接口,配置需要加速的域名,防盗链信息,查看流量监控信息等。同时,CDN 厂商也需要在这里管理用户的各种内部配置,帮助用户处理一些疑问。传统解决方案都是动态页面配合数据库进行的。
当然目前更好的方案是,运营模块只保留展示层,核心部分可以考虑抽象为独立的http api服务,通过这种思路,甚至允许更好的与第三方进行对接配合,分摊一些对于配置关联监控的需求给客户自己去做。
目前 http api 网关还有微服务架构都很火,实际上CDN厂商的技术大部分还比较陈旧。不过也在慢慢的更新。如果打个比方,运营系统类似快递中的下订单部分,用户给出要投递的信息,结账,查看投递信息。

网络管理系统

CDN 系统往往都有成百上千(甚至上万)的节点组成,这样一个庞大的网络系统,小到单机可用性,大到网络拓扑,节点间连通性,互备设置,应急处理都需要跟踪和处理。网络管理系统需要能够跟踪所有接入的系统的服务器,监控服务器的状态,能够根据服务器状态/连路状态自动生成维护工单,向外提供的节点可用性信息,链路状况等数据给调度系统。
CDN中运维是一个很重要的角色,自动化运维,智能化运维。借助云架构来改进CDN韵味水平也是很重要的工作。类似的比喻就是快递系统中,对于运输工具的管理和路由通道的监控。例如:北京到武汉的货运/铁路/航运/空运的动向和可用车次。

负载均衡系统

一个好的 CDN 系统,负载均衡系统也就是调度系统是核心模块,也是含金量最高的模块之一。稍后再单独说一些调度系统。快递系统中,保证快递时效,降低物流成本,提高运输系统的效率,这些都是快递中非常重要的模块。这部分主要都是自行研发, 配合一些开源软件。

分发服务系统

最后一个模块就是真正的分发系统了,我们可以想象成,快递员和分拣员。如果数据还没有缓存在本地,分发服务系统能够将请求数据从上层取回,并发送给请求者。对于恶意攻击,需要做基本的防范。
还要进行相应的请求权限检查(防盗链)。最后记录每个请求和相关信息,用于最后的计费,质量跟踪和其他统计。这里比较成熟的开源软件包括:squid/apache/nginx

一般传统的 CDN 系统在介绍时,没有涉及过多的“数据”作用。其实这也是很正常的,因为传统系统中,“数据”大部分时候被锁死在数据库中。而线上日志有时候为了性能而被关闭!但是随着硬件和数据分析技术的成熟和普及,我相信越来越多的 CDN 厂商早就利用数据来帮助自己的完善自己系统。数据主要可以帮助分发服务系统进行预先的推送,另外也可以优化调度系统,将部分负载搞过的节点流量迁移到低负载节点上。

1.4 调度

在任何一个 CDN 系统中, 调度模块都是最核心的部分,调度模块承载。而大部分的调度是通过 DNS 解析实现的,这就要求DNS在解析时, 可以智能地进行调度工作。

调度一般会考虑很多因素

地域,线路,数据中心负载,请求优先级(当系统负载过高时,优先响应哪些请求),应急流量调度(流量暴涨后,将流量导向到其他位置的选择),成本考虑调度(考虑带宽成本)。除此之外,调度自身的性能,容错,防攻击都是这里需要考虑和解决的。

调度中两个很重要的信息就是ip库的构建和服务器信息的采集。一个质量好的 ip 库可以让调度程序更准确选择地域和ISP。并在异常情况下更好的进行特殊处理。而合理及时的服务器信息,可以帮助调度程序更好的平衡复杂,提高系统整体服务质量,这些信息可以是通过第三方探测的数据,也可以是服务器自身的真实数据。

实际上ip库可以从网上下载:纯真ip库,还可以在ip138上抓取,最后还有公开的 BGP 网络协议。通过综合运用上面的信息,一般都可以得到一个质量比较高的ip库。当然,国内主要的下载软件厂商信息非常大,能获得很多外界无法得到的链路信息和ip信息。这也是下载厂商得天独厚的优势之一。

除了IP库外,如果对复杂需求建模和设计权值来保证调度效果也是CDN系统的核心之一。这部分内容属于各家厂商最重要的部分,因此我也不方便继续深入介绍。

除了DNS调度外,如果使用非DNS调度,那么还可以维护文件和服务器的映射关系,这样可以更精确的进行访问调度,降低流量成本。

1.5 资源的部署方式

CDN 系统实际是一种缓存系统, 客户通过 CDN 系统可以为用户提供更好的带宽质量。但是正常情况下,资源是由客户提供的,因此 CDN 系统会为每个加速域名都记录相关的原始站点信息。

当 CDN 系统第一次请求响应资源时,首先会根据配置的原始站点,进行“回源”操作。这个操作不难想象,在回源操作时,节点将会缓存资源到本地存储,并转发资源给请求方。除了被动的拉取外,一些厂商实现了“推”模式,将预计会成为热点的资源,提前从用户站点下载,并分发到各个节点上。对于一些大的 CDN 厂商来说,节点数量非常多(成千上万),如果同时请求客户源站,就相当于对客户发起了DDoS攻击。因此,基本上CDN系统都会被划分为多个层级。下图就是蓝迅的3层架构:

为了保证系统的可靠性,每个节点存在多个互相备份的顶层节点。只有这些顶层节点才能真正的向客户源站发起“回源”请求。“回源”次数本身也作为CDN系统中一个重要指标,来衡量CDN系统的好与差。CDN 系统中,叶子节点,一般称为边缘节点,边缘节点实际是调度程序返回真实ip地址,而边缘节点可以向上级节点请求资源。下面我简单给出一个通用的回源模块的设计图:

图中负责回源的模块, 需要接收请求进来, 然后根据文件是否下载,决定后续的处理. 如果文件已经缓存在本地,则可以直接进入响应队列。如果没有缓存,应该进行请求合并,允许多个请求者挂在一个下载任务上。这里还有很多细节,比如:文件分块下载,请求是范围请求,构造请求的合法参数等。

这个回源模块可以放在 nginx 中做, 并适当删减一些模块即可. 通信可以通过 ipc/shared memory 进行数据交换. 也可以将这部分功能独立为一个进程. nginx 作为代理服务器, 只做一些数据收集,防盗链校验。

需要注意的是, 后者更适合大文件处理, 例如:百度曾经开源的 OliveHC 就是这个架构。当然不知道为什么后来链接都被删除了,我发现github上还有一个repo,后面会给大家链接。小文件加速实际上需要考虑如何提高处理的请求数量,一般追求iops而非吞吐。这里可以用数学公式计算推满一个1Gbps/10Gbps网卡需要的请求数量和平均请求大小。

这里有很多细小的优化工作,例如:为了提高CDN系统一个关键参数“首包时间”,CDN系统一般要求资源在“回源”时,必须以流水线方式将资源从上级节点拉取到本地存储,并转发给客户。在多层结构中,每个服务都需要做这样的流水线操作,才能最小化延迟。

另外,还需要根据相应的统计信息,删除本地存储的“冷”资源。目前,随着大数据推动,系统的优化空间也越来越大。这也是通过大数据分析,优化单独节点缓存文件策略的一个非常好的切入点。

1.6 对帐,计费和日志

除了分发各种数据外,CDN 系统也要处理对帐,计费和日志的问题。对帐是为了帮助客户确认其购买的带宽,真实有效。防止被其他人盗链,或被恶意刷流量。关于防盗链,后面会专门介绍。

计费一般相对简单,就是根据域名进行带宽的统计,根据每个月的第N峰值(一般是第三峰值)的95%来作为平均流量。这也是常说的95计费。

日志往往需要为客户保留下来,客户可能有自己的反作弊和防盗链策略,可以根据保存的日志信息,进行分析和预警,定期更新相应算法。

1.7 CDN 性能评估

对于一些大客户来说,如何衡量CDN质量成为了一个难题。因为 CDN 系统往往面相全国,甚至世界各地,再加上有不同运营商存在。因此一般简单的测试方法都不具有实际的代表性,因此作为国内早起专门从事CDN 性能监控的公司:基调网络,现在好像叫“听云”可以为用户出具详细的监测报告。帮助客户了解 CDN 厂商的性能。通过“众包”测试工作,听云在全国布点很多,因此采集的准确度很高。

不过听云的监测报告比较贵,对于带宽需求较低的客户来说,意义较小。但是,CDN 系统检测时,随着CDN系统本身负载不同,不同时间的监测效果可能差距较大。因此,监测报告的数据可以用来参考,但是需要注意其是否真实反映了你关注的需求点。

2 网络分发过程中 ISP 的影响

国内的ISP比较多,大ISP就是电信/联通。此外还有:移动,铁通,长宽等等。有超过10家的 ISP 在国内提供服务。虽然移动收购了铁通,但是铁通的运营完全是原有架构。也就是说,虽然实际ISP数量这几年变少了,但是国内互联网本身,还是有多家ISP存在的。

电信和联通占了绝大部分市场,剩下的小ISP占比很低。这些 ISP 之间如果需要相互访问流量,是会产生“跨网间结算“的,另外一些地方的IT无伦处于水平还是预算等问题,还会在系统配制时,设置各种”不正常的“参数。

2.1 DNS 缓存劫持

DNS 协议是互联网最重要协议之一, 但是 DNS 本身有很多的缺陷。DNS 缓存本身作为一个非常重要的系统优化,在国内环境中,却经常带来问题。

一些小地方的DNS节点,可能会修改用户指定的 TTL 时间,将这个时间设置的超大,例如:24-48小时。一旦发生这种情况,通过该DNS的请求,将会长时间无法正常的被调度,该地区的流量和容错都可能受到影响。

但是上面的问题又是无解的,因为这个过程完全是标准流程的结果。为了解决这个问题,才有一些有能力的公司开始使用私有的解析协议,防止 DNS 系统带来的问题。偶尔运营商还会劫持域名(被攻击,错误配置,插入广告地址)。

2.2 运行商结算对 HTTP 协议的缓存影响

当客户端终于拿到了 ip 准备连接目标服务器时,最常用的 HTTP 协议又成为了另一个带来问题的协议。HTTP协议可以用来传输小文件,也可以用来传输大文件。同时允许断点续传等高级特性。很多 FLASH 浏览器就是用 HTTP 协议进行视频播放的。

上面说到,由于 ISP 之间存在着“跨网间结算”问题,因此一些地方的服务器(小运营商,小地区)会进行 HTTP 请求缓存。通过在客户: client == http proxy == server 之间,建立HTTP代理,解析HTTP请求,将请求资源缓存,来节省跨网间结算。这里, 会产生一些问题,例如:计费丢失,相应结果错误,请求错误等。

大部分 CDN 厂商通过 server 端日志进行计费,上面的代理服务器可以减少真实请求数量,因此实际上降低了实际流量。不过一般这类比较少,所以不是太大问题。一些 http proxy 实现有 bug,例如:对于含有:Range请求的 HTTP 服务器,该代理丢掉了 range 信息,将整个文件都返回给了客户,从而造成客户端请求失败。投诉 CDN 服务质量不好。

还有一些 http proxy 会把不同 http 请求的头进行拼装, 引起服务器解析错误. 例如:一个请求中包含了多个 range 信息. 虽然标准 http 支持,但实际业务层不支持。

对于这类问题,一般可以尝试在 HTTP 头和 url 参数中添加随机信息来避免。但是最好的办法, 是请求的链接中直接包含随机路径,让上述的缓存服务器无法缓存所有的信息,还有就是使用https协议。

3 防盗链

3.1 防盗链的目的

防盗链是一场猫捉老鼠的游戏。盗链的目的只有一个:利润。通过盗取他人的流量,吸引客户在自己的网站观看和点击广告,从而实现利润。而防盗链,就是通过创建访问规则,通过规则来识别请求的“合法性”,来决定如何响应请求。如果想单纯通过防盗链来保护资源本身,一般是不属于防盗链这个范畴的。
通过上面的介绍,可以将资源分为两类来对待:带宽价值较低的资源,例如:网站logo图片,js脚本等资源。另一类就是带宽价值较高的:应用,多媒体文件等。对于不同价值的资源,防盗链的方法也越来越高级,越来越复杂。

3.2 防盗链的策略和方法

  • 根据 http 请求头的 referer 信息 正规的浏览器, 会在请求页面时, 将引起该请求的页面url作为 referer 的值嵌入到 http 请求中。因此, 在服务器端就可以通过简单的判断来决定是否返回资源。以前也有很多网站使用这个信息做权限检查。referer有两个问题,导致它一般只用做校验带宽价值低的资源。首先是一些防火墙可能会修改 http 请求头部,导致 referer 信息被设置为空或完全删除。其次,使用各种第三方工具,例如:curl/wget等,都可以随意设置 referer。因此, referer不适合被单独用来保护带宽价值高的资源。
  • 动态url防盗链 动态url是通过程序配合,使某个资源的url在某一次请求或某一段特定时间内合法。换句话说,每个资源的url有一个失效的时间。因此,盗链者拿到url后,不能简单重复的使用。这种方法一般是一些小站使用,因为这个过程往往同时需要动态页面和后端服务器配合起来进行操作,一般不适合大规模的资源分发。
  • 动态参数或cookie防盗链 目前使用比较多的保护策略是基于动态参数或cookie进行的。在每一次请求资源时,动态页面会根据用户信息,时间戳等信息(用户可以自行编辑规则)动态生成一个请求参数。通过http协议将这个信息发送到服务器后端,后端会根据同样的信息计算并验证请求参数的合法性来决定返回结果。这个生成的规则可能会被破解,也可以适当引入更加复杂的安全校验来规避风险。另外配合访问日志的信息,可以分析流量请求的模式,根据前端SDK信息来分析请求的合法性,定期升级防盗链算法和相关参数。

所以防盗链本身不难,主要还是设计规则的合理性上。要兼顾性能和安全,切忌杀鸡用牛刀。

4 内容分发系统的问题和应对思路

4.1 流媒体分发

流媒体分发时,一般对于 flv 的支持会更好一些。原因是 flv 是基于文件偏移进行快进和倒退的。而mp4编码,是根据时间进行快进和倒退的。某些CDN厂商可能对 mp4 的支持不好或者根本不支持。但是 flv 一般是可以直接支持的。实际上flv格式是通过播放器进行了一些偏移计算,因此降低了对分发服务器的技术要求。这里的难点,主要是前面讲的回源模块本身复杂带来的。如果需要额外处理索引,程序层面也会比较复杂。

除此之外,分发的流媒体如果体积比较大,可以考虑主动对文件进行切片(小于100MB)。这样对于某些配置较差的服务器,可以做一些优化。例如:没有阵列或者阵列卡比较差的机器上,避免将一个大文件放置在一个单独磁盘,从而可以最大化的从多个磁盘上读取该文件,有效提高吞吐。

前端 SDK 最好能够收集数据,例如:发起客户ip,连接服务器的ip,解析服务器ip的时间开销。连接服务器ip的时间开销,首包时间开销,数据中断比例。服务器返回状态值,数据传输时间等。因为在整个网络中,存在一些“代理服务器”,因此,某些请求可能根本没有到达服务器或请求被修改过。通过前后端共同保留日志,可以更佳清晰的分析结果,以便改进方法,提高用户的体验。数据是推动系统进步的一个非常重要的组成部分。

防盗链的设计应该考虑:在不严重影响客户端性能和服务器端性能下,让破解盗链规则的难度尽可能高。虽然 referer 很容易被伪造,但是仍然可以作为第一道防线过滤一部分请求。通过复杂的规则, 来提高盗链的成本。通过前后端日志分析,了解流量的消费情况,定期按需修改防盗链算法。

4.2 应用分发

现在手机应用分发非常多,也有不少人遇到过链接劫持的问题。如果面对 dns 劫持,基本上只能使用第三方解析方案,例如 HttpDns。如果是http这层被“代理服务器”缓存,那么像前面所说,可以尝试构造动态url来组织被缓存。对于 http 劫持,大家可以参考参考信息中的链接,介绍的很详细。从原理上了解了问题本质后,一些手段会更有针对性,但是也会发现一些问题并非很容易解决。发现问题后,可以尽快投诉。所以大家可以晚点看我给出的参考链接,了解如何定位各种劫持。

4.3 nginx 在 Linux 上的性能优化

相对于 CDN 系统来说, 服务器程序主要使用系统上的网络IO和磁盘IO。对于小请求(几KB到几十KB)来说,衡量的关键指标更偏重于每秒可以响应的请求数量。因为请求文件小,因此 nginx 有很多优化针对小文件。例如 sendfile 功能,可以避免将文件读取到内存(经过系统缓存到用户内存,再传递给网络接口的系统用),而直接让操作系统内核发送该文件。当然,这个功能也有缺点,就是如果文件太大,会导致带宽被某个请求占用,因此nginx内部做了限制,防止这种情况的出现。相对来说,大请求一般情况更关注磁盘IO和内存的优化。请求较大时,nginx 通过一个定长buffer来切割每个请求消耗的网络和磁盘IO。这样可以更公平的将有限的IO分配给多个请求,既不会浪费,也不会导致不均匀。


 

nginx 本身采用了事件模型驱动,多进程下,正常情况下每个进程只有一个线程。但是事件模型允许即使一个线程,也可以响应成千上万的请求。

当 nginx 运行在 linux 系统上时,如果服务的文件的存储大小比机器内存大比较多,并且这些文件都是热点文件时,连接 nginx 服务器可能会引起连接超时或链接建立过慢的问题。

这个问题要从两个方面来解释: linux 的文件访问操作上分为两类。

一类是利用操作系统的虚拟存储来缓存热点文件,因此可以提高磁盘访问速度。还有一类接口被称为直接访问模式,该模式会绕过操作系统缓存,直接将文件加载到用户进程内存空间。而 linux 上,第一类访问模式不支持“异步操作”,也就是不兼容事件模式。而第二类访问模式虽然兼容“异步操作”,但是因为没有操作系统进行磁盘缓存,导致这里接口不友好。第二类主要是没有缓存管理,系统的性能会大幅下降。nginx 在 linux 上,一直以来都适用第一类访问模式进行操作。nginx 的设计目标就是多进程提供更好的稳定性,降低进程间的交互。如果使用第二类模式,那么就会增加复杂度,并且让进程之间的交互引入更多封锁(考虑支持数据缓存机制)。这也就是如果请求的资源无法放入系统的内存中,就会导致事件模型被文件操作卡住,无法正常的响应连接。

在 nginx 1.7.12 及之后的 1.8 中,nginx通过引入 thread pool 来缓解上面的问题。主线程决定要发起文件系统操作时,将会创建一个特殊的作业,并将该作业丢到作业队列中。而线程池中的线程会不断的执行该队列的文件任务,然后将执行好的结果放入返回队列,主线程就会继续后续操作。通过这个操作,主线程不会再被阻塞住,因此建立连接将不会被卡住。

但是,如果 IO 严重不足时,请求时间仍然会很长,还是可能让客户端请求超时。这种case,可以进行其他优化,例如磁盘调度算法,优化文件存储结构,升级存储等。之前有一片文章说,nginx使用线程池性能提升9倍,实际就是说在linux上性能问题。该问题在FreeBSD系统上不存在,因为FreeBSD系统的异步IO支持使用内存作为文件缓存。

Linux上之所以不支持,也是因为社区一直扯皮。而非系统自身能力问题。

4.4 如何节省成本

CDN 的价格不是特别透明,大牌厂商一般都是和销售来谈。而且这中间还会根据不同流量有一些折扣。 但是市面上 CDN 价格基本可以认为:

小文件价格 > 流媒体价格 > 下载类价格

而直播的价格也会高于点播类的流媒体价格。

如果签署的价格协议是按照标准的峰值带宽+95计费方式,那么消峰往往是一个比较常见的方式。但是消峰要根据具体的使用场景来进行,例如下面的场景可能不适用或属于消峰:紧急发布一个修复严重bug或安全漏洞的版本,这时候,可能会提示用户尽快升级,可能会造成一个特别高的峰值。开辟新业务,旧流量没有明显改变下,在某些热点时段产生新高峰。被大规模盗链,引起额外的流量,产生新高峰。消峰的方法就是将请求错开,避免同一时间出现请求,下面场景比较适合消峰:发布非重要的升级,期望用户逐步过渡。可以通过限制通知用户升级的数量,来减少峰值出现。自动化日志分析,针对异常流量,有自动化应急预案,例如:自动拒绝部分请求。

4.5 嵌入SDK 的对于客户的影响

实际上类似像 HttpDns 或者 p2p 加速这里 sdk 都会遇到客户担忧的几点:代码安全性问题,体积大小引发的CDN成本上涨,稳定性问题,集成的额外代价(小客户没有人力或能力),需求是否真实存在(小客户可能没有精力考虑这些)。这也是 SDK 方案往往遇到难以推广的问题。开源 SDK 从很大程度上可以降低客户对代码安全性的担忧,但是成本,集成代价都是不太好解决的。

5.P2P穿墙打洞

下面加上一点临时补充的内容,也是来自网上,我简单的组织了一下。帮助大家简单了解P2P里面一个关键技术, 打洞穿墙。

一般P2P虽然是多对多的传输, 但实际上, 可以分解为: 控制部分和传输部分. P2P 网络中需要一些服务节点, 用于交换信息和协调打洞。当然这些服务节点一般还会有查询资源位置和相关节点的功能。 传输部分中涉及的实体分两类:可以直接被访问的实体和隐藏在NAT后面的实体。只要有至少一方可以直接被访问,那么利用控制部分就可以建立传输通道,也就不需要进行打洞。当两个实体都被隐藏在NAT后面时, 才有打洞这个问题。

所谓打洞,实际上是指隐藏在 NAT 内部服务器通过连接外部实体时,在 NAT 服务器上留下的一个“临时”的映射关系。这样 NAT 服务器才能正确的将外网的数据包,发送给内部实体。

在 P2P 打洞时,每个实体都需要主动连接 P2P网络的服务器,将自己的外网IP和打洞出来的“临时”端口上报到服务器。这样服务器就可以根据该实体的资源信息和网络信息一起保存下来,为后续请求连接的人提供输入参数。

当实体A准备连接实体B时,只需要通过 P2P网络的服务器获取连接信息就可以直接进行连接了。因为“临时”的洞在之前已经建立好了。

这里其实有一些额外的要求:

  • 每个实体必须周期性的像 P2P网络的服务器发送心跳,该心跳是为了保证打洞的“临时”端口不会被清理;
  • 该 NAT 服务器是 Cone 类型服务器,也就是说,所有外部主机向这个端口发送的信息,都能被转发给打洞的主机。这类 NAT 服务器占大部分情况。

如果 NAT 打洞失败,可以考虑放弃或者转而使用服务器转发模式。

上面介绍的是比较简单的UDP打洞,TCP也是可以穿墙打洞的,但是比较复杂,这里我也没有太多发言权。国内的厂商在穿墙打洞上确实有很多高手,对于国内复杂的互联网环境,简单的算法不能解决很多细节问题。正因为这些厂商在相关领域做了很久,才使得“高速通道”中的P2P传输效果非常好。

今天分享的内容,都来自下面的链接。大家如果愿意对上面内容细节有更深入的了解,可以针对性的阅读参考信息。

参考信息:

  1. CDN内容分发网络架构与四大关键技术 http://www.idcquan.com/CDN/720016_2.html
  2. CDN技术详解 http://book.2cto.com/201207/327.html
  3. Nginx开发从入门到精通 http://tengine.taobao.org/book/
  4. nginx 线程池原文: https://www.nginx.com/blog/thread-pools-boost-performance-9x/
    nginx 线程池翻译: http://www.infoq.com/cn/articles/thread-pools-boost-performance-9x
  5. 浅析我国互联网骨干网网间结算问题 (http://blog.chinaunix.net/uid-20486655-id-261838.html)
  6. nginx API 网关介绍: https://www.nginx.com/solutions/api-gateway/
  7. nginx 微服务架构: https://www.nginx.com/blog/introduction-to-microservices/
  8. dns 劫持/http 劫持: http://bbs.kafan.cn/thread-1825061-1-1.html
  9. CDN缓存那些事 http://bbs.qcloud.com/forum.php?mod=viewthread&tid=3775
  10. 全局精确流量调度新思路-HttpDNS服务详解 http://blog.csdn.net/zhaqiwen/article/details/42024045
  11. 百度曾经开源的 cdn 缓存工具OliveHC(国内已经关闭): https://github.com/Jacky-Li/olivehc
  12. 浅谈网站防盗链技术 http://bbs.csdn.net/topics/110042791
  13. Nginx防盗链详细解说 http://blog.csdn.net/yuwenruli/article/details/8541952
  14. 随机 url 等相关信息: http://stackoverflow.com/questions/29674755/a-single-regex-for-all-location-paths-regardless-of-the-name-in-nginx http://stackoverflow.com/questions/367786/prevent-caching-of-ajax-call http://stackoverflow.com/questions/126772/how-to-force-a-web-browser-not-to-cache-images
  15. 探密诡异的HTTP Referer总是为空的原因 http://www.cnblogs.com/dreamstudio/archive/2009/04/01/1427202.html
  16. P2P内网穿透原理 http://bbs.cnhonker.com/forum.php?mod=viewthread&tid=7479
  17. P2P之UDP穿透NAT的原理与实现 [转] http://blog.csdn.net/lsaturn/article/details/29262
  18. 从ip138网站爬取ip所处地点 http://blog.csdn.net/jthink_/article/details/28597757
  19. Nginx做前端Proxy时TIME_WAIT过多的问题 http://www.cnblogs.com/qleelulu/p/3601499.html
  20. UDP穿透NAT的原理与实现(UDP“打洞”原理)http://blog.csdn.net/overmaker/article/details/3201799

QA

Q1:CDN的首次域名解析慢,测试发现很多都需要几百ms,怎么优化?

A1:首次查询因为没有缓存,确实会更慢。这个过程可能需要根据dig工具开始, 不断用迭代查询, 判断哪台dns服务器解析慢. 然后要求这个服务器的管理者优化解析. 可能是自己的dns慢,也可能是CDN厂商的CDN服务器慢。需要逐步的定位服务器。

Q2:顶级节点 回源 操作获取的资源文件是采用分布式存储和管理的吧?会限制单个顶级节点的管理的资源大小吗?

A2:这个问题很赞,但是因为不太了解各个厂家的情况,所以没办法给出统一和完整的答案。但是考虑到节点众多,以及客户规模不同,节点实际还会被分组。就是一部分节点只给一部分客户用,这样减少了顶级节点的存储压力。 同时,确实需要使用分布式存储,这样在容错和存储大小上都会更加从容。顶级节点也会有容量限制,一样会清理资源。这也是“回源次数”是一个很重要的CDN衡量指标。

Q3:对不涉及目前内容下载的加速 CDN的意义就是打通各大运营商人为设置的障碍和负载均衡吗? 比如物联网设备接入加速。

A3:抱歉,我基本接触的都是媒体加速和下载类加速。但是从我刚开始做CDN,到现在为止,我认为各大运营商之间的障碍是一个非常痛苦和漫长的过程。因此,如果说不考虑加速,那么CDN确实有这些意义。 另外解决不同地区间的最优路径选择上,CDN系统确实也更有优势。特别是晚上流量高峰时期,省间骨干网络的质量确实会下降很多。希望能帮助你。

Q4:在使用第三方CDN时,客户https证书是怎样管理的呢?

A4:这个我之前的业务范畴确实没做到这么深入,因为我们加速的大部分内容,还都是简单的http。不过你这个问题特别好,我也之前确实看到过两篇关于CDN和ssl的资料。目前CDN+ssl性能好像不是特别好,特别影响页面的加载,另一个是CDN对网站的安全支持很有限,我可以继续往下看看这边。

想进一步了解CDN的架构细节?或想同群专家进一步交流CDN经验及高可用架构,可回复arch申请进群。

本文策划 陈刚@北京智识, 内容由刘世杰、陈刚、四正编辑与发布,其他多位志愿者对本文亦有贡献。读者可以通过搜索“ArchNotes”或长按下面图片,关注“高可用架构”公众号,查看更多架构方面内容,获取通往架构师之路的宝贵经验。转载请注明来自“高可用架构(ArchNotes)”公众号,敬请包含二维码!

CDN对流媒体和应用分发的支持及优化 | 高可用CDN架构详解
标签: