使用内容发布网络
网站最初通常将其所有的服务器放在同一个地方。当用户群增加时,公司就必须面对服务器放置地点不再适用的事实,有必要在多个地理位置不同的服务器上部署内容。如果应用程序 web 服务器离用户更近,则一个 http 请求的响应时间将缩短。
内容发布网络(CDN)是一组分布在多个不同地理位置的 web 服务器,用于更加有效地向用户发布内容。向特定用户发布内容的服务器的选择基于对网路可用度的测量。例如,CDN 可能选择网络阶跃数最小的服务器,或者具有最短响应时间的服务器。
除了缩短响应时间之外,CDN 还可以带来其他优势。如备份、扩展存储能力、缓存、缓和 web 流量峰值压力。
CDN 的缺点是你的响应时间可能会受到其他网站的影响,另外的缺点是你无法直接控制组件服务器所带来的特殊麻烦。例如,修改 http 响应头必须通过服务提供商来完成,如果 CDN 服务的性能下降了,你的工作质量也随之下降。
CDN 用于发布静态内容,如图片、脚本、样式表和 flash。提供动态 html 页面会引入特殊的存储需求,比如数据库连接、状态管理、验证、硬件和 os 优化等。这些复杂性超越了 CDN 的能力范围。
添加 Expires 头
规则 3 展示了如何配置组件,使其能够最大化地利用浏览器的缓存能力来改善页面的性能。
页面的访问者会进行很多 http 请求,但通过使用一个长久的 expires 头,使这些组件可以被缓存。长久的 expires 头最常用于图片,但应该将其用在所有组件上,包括脚本、样式表和 flash。
Expires 头
web 服务器使用 expires 头来告诉 web 客户端它可以使用一个组件的当前副本,直到指定的时间为止。http 规范中简要地称该头为“在这一日期 / 时间之后,响应将被认为是无效的”。它在 http 响应中发送。
Expires: Thu, 15 Apr 2010 20:00:00 GMT
它告诉浏览器该响应的有效性持续到 2010 年 4 月 15 日为止。在到期前,浏览器在后续的页面浏览中会使用缓存的图片。
Max-Age 和 mod_expires
HTTP1.1 引入了 Cache-Control 头来克服 Expires 头的限制。因为 Expires 头使用一个特定的时间,它要求服务器和客户端的时钟严格同步。另外,过期日期需要经常检查,并且一旦未来这一天到来了,需要再服务器配置中提供一个新的日期。
Cache-Control 使用 max-age 指令指定组件被缓存多久。它以秒为单位定义了一个更新窗。如果从组件被请求开始过去的秒数少于 max-age,浏览器就使用缓存的版本,这就避免了额外的 Http 请求。一个长久的 max-age 头将刷新窗设置为未来 10 年。
Cache-Control: max-age=315360000
使用带有 max-age 的 Cache-Control 可以消除 Expires 的限制,你可以同时指定这两个响应头——Expires 和 Cache-Control max-age。如果两者同时出现,HTTP 规范规定 max-age 指令将重写 Expires 头。
对于 Expires 带来的时钟同步和配置维护问题,mod_expires Apache 模块使你在使用 Expires 头时能够像 max-age 那样以相对的方式设置日期。
下例中,过期时间被设计为自请求开始的 10 年之后:
<FilesMatch "\.(gif|jpg|js|css)$">
ExpiresDefault "access plus 10 years"
</FilesMatch>
它同时向相应中发送 Expires 头和 Cache-Control max-age 头。
Expires: Sun, 16 Oct 2016 05:43:02 GMT
Cache-Control: max-age=315360000
由于 Cache-Control 具有优先权,同时在 HTTP1.0 浏览器 Expires 生效。
不仅仅是图片
长久的 Expires 头应该包含任何不经常变化的组件,包括脚本、样式表和 Flash 组件。
修订文件名
如果我们将组件配置为可以由浏览器代理缓存,当这些组件改变时用户如何获得更新呢?当出现了 Expires 头时,直到过期为止一直会使用缓存的版本。
最有效的解决方案是修改其所有链接,这样,全新的请求将从原始服务器下载最新的内容。通常将版本号嵌在组件的文件名中。
总结
如果没有长久的 Expires 头,它仍然会存储在浏览器的缓存中。在后续请求中,浏览器会检查缓存并发现组件已经过期。为了提高效率,浏览器会发送一个 GET 请求。如果组件没有改变,原始服务器可以免于发送整个组件,而是发送一个很小的头,告诉浏览器可以使用其缓存的组件。
这些条件请求加起来,就是缓存节省的时间。