{"action":"opened","issue":{"url":"https://api.github.com/repos/renaesop/blog/issues/1","repository_url":"https://api.github.com/repos/renaesop/blog","labels_url":"https://api.github.com/repos/renaesop/blog/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/renaesop/blog/issues/1/comments","events_url":"https://api.github.com/repos/renaesop/blog/issues/1/events","html_url":"https://github.com/renaesop/blog/issues/1","id":153362268,"number":1,"title":"面向前端的CDN原理介绍","user":{"login":"renaesop","id":5894477,"avatar_url":"https://avatars.githubusercontent.com/u/5894477?v=3","gravatar_id":"","url":"https://api.github.com/users/renaesop","html_url":"https://github.com/renaesop","followers_url":"https://api.github.com/users/renaesop/followers","following_url":"https://api.github.com/users/renaesop/following{/other_user}","gists_url":"https://api.github.com/users/renaesop/gists{/gist_id}","starred_url":"https://api.github.com/users/renaesop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/renaesop/subscriptions","organizations_url":"https://api.github.com/users/renaesop/orgs","repos_url":"https://api.github.com/users/renaesop/repos","events_url":"https://api.github.com/users/renaesop/events{/privacy}","received_events_url":"https://api.github.com/users/renaesop/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/renaesop/blog/labels/web%E6%80%A7%E8%83%BD","name":"web性能","color":"f9d0c4"},{"url":"https://api.github.com/repos/renaesop/blog/labels/%E7%BD%91%E7%BB%9C","name":"网络","color":"fef2c0"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2016-05-06T01:45:03Z","updated_at":"2016-05-06T01:45:03Z","closed_at":null,"body":"> 内容分发网络（Content delivery network或Content distribution network，缩写：CDN）是指一种通过互联网互相连接的电脑网络系统，利用最靠近每位用户的服务器，更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户，来提供高性能、可扩展性及低成本的网络内容传递给用户。\r\n\r\n### 为什么需要CDN\r\n\r\n根本上的原因是，访问速度对互联网应用的用户体验、口碑、甚至说直接的营收都有巨大的影响，任何的企业都渴望自己站点有更快的访问速度。而HTTP传输时延对web的访问速度的影响很大，在绝大多数情况下是起决定性作用的，这是由TCP/IP协议的一些特点决定的。物理层上的原因是光速有限、信道有限，协议上的原因有丢包、慢启动、拥塞控制等。\r\n\r\n要提高访问速度，最简单的做法当然就是多设置几个服务器，让终端用户离服务器“更近”。典型的例子是各类下载网站在不同地域不同运营商设置镜像站，或者是像Google那样设置多个数据中心。但是多设几个服务器的问题也不少，一是多地部署时的困难，二是一致性没法保障，三则是管理困难、成本很高。实际上，在排除多地容灾等特殊需求的情况下，对大多数公司这种做法是不太可取的。当然，这种方案真正做好了，甚至是比后续所说的使用CDN要好的。\r\n\r\nCDN是一种公共服务，他本身有很多台位于不同地域、接入不同运营商的服务器，而所谓的使用CDN实质上就是让CDN作为网站的门面，用户访问到的是CDN服务器，而不是直接访问到网站。由于CDN内部对TCP的优化、对静态资源的缓存、预取，加上用户访问CDN时，会被智能地分配到最近的节点，降低大量延迟，让访问速度可以得到很大提升。\r\n\r\n### CDN的原理\r\n\r\n> CDN做了两件事，一是让用户访问最近的节点，二是从缓存或者源站获取资源\r\n\r\nCDN有个源站的概念，源站就是提供内容的站点(网站的真实服务器), 从源站取内容的过程叫做回源。\r\n\r\n每次访问的具体流程如图（以最普通的CDN为例）\r\n\r\n![流程图](//nzqni3ys9.qnssl.com/cdn.svg)\r\n\r\n具体举个例子：\r\n\r\n用户在首次访问 [https://assets-cdn.github.com/pinned-octocat.svg](hhttps://assets-cdn.github.com/pinned-octocat.svg) , 假设不委托local DNS服务器递归查询，会经历以下几个过程\r\n\r\n1. 浏览器检查本地有没有这个东东的有效缓存，有则使用缓存，没有有效缓存则进行对`assets-cdn.github.com`的DNS查询，获得一个 CNAME记录, `igithub.map.fastly.net`,值得注意的是，多个加速域名可以解析到同一个CNAME，CDN回源和缓存的时候考虑到了hostname，👍；\r\n2. 进行对`github.map.fastly.net`的DNS查询，获得一个A记录，有两个地址`103.245.222.133`, 这一步对CDN来说时十分重要的，它给出了离用户最近的边缘节点；\r\n3. 浏览器选一个返回的地址，然后进行真正的http请求，开始向`103.245.222.133`握手，握手完了把http请求头也发给了该边缘服务器;\r\n4. 边缘服务器检查自己的cache里面有没有`https://assets-cdn.github.com/pinned-octocat.svg`这个资源，有则返回给用户，如果没有，向CDN中心服务器发起请求;\r\n5. CDN中心服务器检查自己的cache里面有没有这个资源，有则返回给边缘服务器，没有则回源;\r\n6. 中心服务器发现客户配置了`github.map.fastly.net`的回源地址(这个只有cdn会知道，假设是`xxx.xxx.xxx.xxx`)，就把http请求发到源站地址上，源站返回后返回给请求方;\r\n\r\n可以看出CDN加速的原理很大部分是跟DNS挂钩在一起的，CDN供应商几乎一定需要一个智能DNS服务器。\r\n\r\n上述步骤每一步都可以缓存，注意是每一步！ 所以CDN要清除缓存很难，因为有很多服务器上的缓存要清除。无论是用户对边缘服务器的请求，还是CDN服务器的回源都可以使用https。\r\n\r\n注意，实际环境中图中每个服务器都可以是集群，甚至CDN分区域中心和总中心。"}}