网站首页 > 技术教程 正文
前面几节课,我们了解了缓存,包括本地缓存、分布式缓存及使用场景,包括分布式集群的高可用方案。那么你的架构就变成了如下:
这个架构中,我们利用分布式缓存对动态请求数据读取做了加速,但是我们的系统中存在大量的静态资源文件。
对于移动app来说,这些静态资源主要是图片、视频、流媒体消息。对于web网站来说则包括了javascript\css\静态HTML等。
具体到示例中的电商系统,商品的图片、介绍商品使用方法的视频等静态资源文件都放在了Nginx等web服务器上,他们的读请求量极大,并且对访问速度的要去极高,还占据了很高的带宽,这时会出现访问速度慢带宽沾满影响动态请求的问题,那么你就需要考虑如何通过加速这些静态资源文件了。
静态资源加速的考虑点
那么我们不可用通过分布式缓存实现吗?不可以的,分布式缓存也不能保证资源文件的就近传输问题。
所以,静态资源文件的关键点是就近访问。这样才能达到性能最有。
所以 我们考虑在业务服务器上层增加一层特殊的缓存,用来承担绝大部分对于静态资源的访问,这一层特殊访问的节点需要遍布在全国各地,这样可以让用户选择最近的节点访问。缓存的命中率也需要一定的保证,尽量减少资源存储源站的请求数量-回源请求,这一层缓存就是CDN
CDN 的关键技术
CDN(Content Delivery Network/Content Distribution Network,内容分发网络)。简单来说就是将静态资源分发至位于不同地理位置的服务器上,这样就可以就近访问静态资源文件,加快访问速度。
如何让用户的请求到达 CDN 节点
首先,我们考虑一下如何让用户的请求到达 CDN 节点,你可能会觉得这很简单啊,只需要告诉用户 CDN 节点的 IP 地址,然后请求这个 IP 地址上面部署的 CDN 服务就可以了啊。但是这样会有一个问题:就是我们使用的是第三方厂商的 CDN 服务,CDN 厂商会给我们一个 CDN 的节点 IP,比如说这个 IP 地址是“111.202.34.130”,那么我们的电商系统中的图片的地址很可能是这样的:“http://111.202.34.130/1.jpg”, 这个地址是要存储在数据库中的。
那么如果这个节点 IP 发生了变更怎么办?或者我们如果更改了 CDN 厂商怎么办?是不是要修改所有的商品的 url 域名呢?这就是一个比较大的工作量了。所以,我们要做的事情是将第三方厂商提供的 IP 隐藏起来,给到用户的最好是一个本公司域名的子域名。
那么如何做到这一点呢?这就需要依靠 DNS 来帮我们解决域名映射的问题了。
DNS(Domain Name System,域名系统)实际上就是一个存储域名和 IP 地址对应关系的分布式数据库。而域名解析的结果一般有两种,一种叫做“A 记录”,返回的是域名对应的 IP 地址;另一种是“CNAME 记录”,返回的是另一个域名,也就是说当前域名的解析要跳转到另一个域名的解析上。实际上 www.baidu.com 域名的解析结果就是一个 CNAME 记录,域名的解析被跳转到 www.a.shifen.com 上了,我们正是利用 CNAME 记录来解决域名映射问题的,具体是怎么解决的呢?我给你举个例子。
比如你的公司的一级域名叫做 example.com,那么你可以把你的图片服务的域名定义为“img.example.com”,然后将这个域名的解析结果的 CNAME 配置到 CDN 提供的域名上,比如 uclound 可能会提供一个域名是“80f21f91.cdn.ucloud.com.cn”这个域名。这样你的电商系统使用的图片地址可以是“http://img.example.com/1.jpg”。
用户在请求这个地址时,DNS 服务器会将域名解析到 80f21f91.cdn.ucloud.com.cn 域名上,然后再将这个域名解析为 CDN 的节点 IP,这样就可以得到 CDN 上面的资源数据了。
不过这里面有一个问题:因为域名解析过程是分级的,每一级有专门的域名服务器承担解析的职责,所以域名的解析过程有可能需要跨越公网做多次 DNS 查询,在性能上是比较差的。
从“ 域名分级解析示意图”中你可以看出 DNS 分为很多种,有根 DNS,顶级 DNS 等等。除此之外还有两种 DNS 需要特别留意:一种是 Local DNS,它是由你的运营商提供的 DNS,一般域名解析的第一站会到这里;另一种是权威 DNS,它的含义是自身数据库中存储了这个域名对应关系的 DNS。
下面我以 www.baidu.com 这个域名为例给你简单介绍一下域名解析的过程:
- 一开始,域名请求解析,会先检查本地hosts文件,查看是否有 www.baidu.com对应的IP
- 如果没有的话,就请求local dns 是否有域名解析缓存的结果,如果有就返回标识是从非权威DNS返回的结果
- 如果没有就开始dns的迭代查询先请求根 DNS,根 DNS 返回顶级 DNS(.com)的地址;再请求.com 顶级 DNS 得到 baidu.com 的域名服务器地址;再从 baidu.com 的域名服务器中查询到 www.baidu.com 对应的 IP 地址,返回这个 IP 地址的同时标记这个结果是来自于权威 DNS 的结果,同时写入 Local DNS 的解析结果缓存,这样下一次的解析同一个域名就不需要做 DNS 的迭代查询了。
- 经过了向多个 DNS 服务器做查询之后,整个 DNS 的解析的时间有可能会到秒级别,那么我们如何来解决这个性能问题呢?
一个解决的思路是:在 APP 启动时对需要解析的域名做预先解析,然后把解析的结果缓存到本地的一个 LRU 缓存里面。这样当我们要使用这个域名的时候,只需要从缓存中直接拿到所需要的 IP 地址就好了,如果缓存中不存在才会走整个 DNS 查询的过程。同时为了避免 DNS 解析结果的变更造成缓存内数据失效,我们可以启动一个定时器定期地更新缓存中的数据。

本文暂时没有评论,来添加一个吧(●'◡'●)