中文站

云原生应用架构实践-静态资源分离

4.3 系统优化

系统扩展,着眼点是系统节点的横向扩展,重点是增加系统的整体吞吐量,对于提升 用户单次访问没有什么帮助。相反,加入更多横向扩展的中间设施和各种逻辑,往往会减 慢而不是加快用户的访问速度。

无论什么产品,最终要为用户服务,因此除了服务端的承载能力之外,用户的访问性能、产品本身单点稳定也是要考虑的内容。从某种角度上来说,用户访问性能比服务端整 体性能更为重要,因为这会切实影响到用户的实际体验。如果说系统扩展是“外功绝学”
, 重点在于系统的整体表现,系统优化就是“内功心法”,重点提高系统内部的处理能力和稳 定性,为用户带来更好的体验。

4.3.1 静态资源分离

静态资源分离是指将静态资源,比如图片、视频、文档、HTML、JavaScript、CSS 与 后台应用程序提供的动态查询、页面动态渲染等进行隔离。之所以进行隔离是静态资源和 动态资源具有各自不同的特点,需要分别进行优化。

静态资源有以下特点。 

几乎从不修改、可以长期缓存:图片、视频发布之后就基本不会修改或者删除。

带宽要求高、流量较大:互联网上绝大部分流量是由静态资源的访问引起的,典 型的有视频网站的流量、电商网站海量的商品图片等。
动态资源有以下特点。

可变数据,不能缓存,或只能短期缓存:动态资源请求譬如查询当前用户购物车 的商品列表、查询商品的库存信息、微博上面的评论列表。一般都涉及结构化数 据或者半结构化数据的访问,为了减小数据库的访问压力,会使用 Redis、 Memcached 这类缓存组件进行内存缓存,但是这些数据在自身的生命周期中是经 常变化的,如果发生变化,我们需要及时维护这些缓存信息的新鲜度。

带宽要求低、QPS 要求高:此类数据的访问带宽需求相比于图片视频完全不在一 个量级,一个请求基本都在 1K 以内,但是由于不能缓存,对底层缓存和存储系 统的 QPS 要求相对而言就会比较高。

基于动态资源和静态资源各自不同的特点,动静资源的最佳实践就是进行隔离。静态 资源基本上都可以托管在对象存储系统上,譬如网易云对象存储服务 NOS、AWS S3 等。

隔离的优势如下。

提升性能。

更好的扩展性。

静态资源服务和业务服务可以单独部署。 

静态资源分离实践,包括使用独立域名、避免域名绑定、CDN 服务等。

1. 使用独立域名

在一些大型网站中,我们发现静态资源都放在不同的域名下面,这样做有很多原因。
浏览器并发限制 

浏览器对单个域名下的访问有并发限制,现在大部分浏览器都是使用 HTTP 1.1 的模 式,HTTP 1.1 的典型交互方式为 ping-pong,在广域网(公网)场景下并不能很好地利用网 络的带宽。如图 4-15 所示。 

图 4-15 HTTP 1.1 模式的并发限制

参考 

为了提升网站的加载速度,浏览器通常都会针对单个域名打开并发的几个 TCP 连接。表 4-3 为不同浏览器版本对并发的支持情况。

数据来源:http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/

并发即为同一时间进行同一域名的 HTTP 请求限制。如果请求数目超出限制,则会阻 塞。因此,网站中对一些静态资源使用不同的一级域名,可以大大加速加载速度。

避免 Cookie 的传递 

静态资源与主服务不在同一域名下,就可以避免每次 Web 端无意义的 Cookie 传输, 因为一般静态资源的访问不需要 Cookie 的参与。例如 http://163.com 设置 Cookie,所有子 域名都会带上 Cookie。

2. 避免域名绑定 

如使用第三方厂商提供的静态资源托管服务,最好不要用厂商提供的域名,否则很容 易被限定在一个托管服务商上。应该用自己的域名绑定到相应的静态资源托管服务商,因 为谁也不能保证谁比谁活得更加长久,假如托管方由于各种原因停止服务,那么我们至少 可以直接把数据迁移到其他可用的托管厂商,直接将域名切换到新厂商,继续提供服务。 

3. 使用 CDN 缓存

还有很关键的一点是静态资源可以通过 CDN(Content Delivery NetWork)加速。源站 内容同步到全国各边缘节点,配合精准的调度系统,将用户的请求分配至最适合的节点, 比如北京的用户直接在北京城域网就近访问,用户可以以最快的速度取得所需的内容,解 决网络带宽小、用户访问量大、网点分布不均等问题,提高用户访问的响应速度。各大云 计算厂商一般都会提供 CDN 服务,各大公有云厂商大都提供了自助化平台帮助用户更方便 地使用 CDN 进行静态资源加速。使用 CDN 的资源还需要注意以下两点。

资源划分 

静态资源类型很多,比如 JavaScript 脚本、HTML 静态页面、图片、视频等,对于不 同类型的文件,我们对其缓存时间、访问方式和服务要求都可能是不一样的。譬如 JavaScript 脚本、HTML 页面、小图片这类资源一般对服务质量要求较高,它们展现快速, 文件较小。视频媒体点播加速一般要求传输稳定、不卡即可,它们存储量较大。所以这些 静态资源最好划分到不同站点下。

版本化管理 

由于 CDN 是缓存用户的资源,比如用户的头像,假设通过 CDN 进行加速,如果用户 直接使用同名文件覆盖,很容易导致源站资源更新,但是 CDN 资源长期更新不了,用户看 不到最新上传的头像。虽然 CDN 一般都提供了 Purge 的方式来清理缓存的资源,但是 Purge 操作相对来说成本比较高,因为 CDN 边缘节点成千甚至上万,要把 Purge 请求分发到所有 的节点并保证执行有效,会带来较大的开销,且不说能否执行成功,即便执行成功也需要 10 分钟左右的时间。所以,应用最好使用版本化的方式更新资源,比如刚开始头像为 mylogo-version1.jpg,更新之后文件名为 mylogoversion2.jpg,那么用户下次访问的时候可以 访问 mylogo-version2.jpg 获取最新的头像。

文章节选自《云原生应用架构实践》 网易云基础服务架构团队 著