《高性能网站建设指南》规则2、3—使用内容发布网络、添加Expires头
使用内容发布网络
网站最初通常将其所有的服务器放在同一个地方。当用户群增加时,公司就必须面对服务器放置地点不再适用的事实,有必要在多个地理位置不同的服务器上部署内容。如果应用程序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响应中发送。
1 | 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年。
1 | 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年之后:
1 | <FilesMatch "\.(gif|jpg|js|css)$"> |
它同时向相应中发送Expires头和Cache-Control max-age头。
1 | Expires: Sun, 16 Oct 2016 05:43:02 GMT |
由于Cache-Control具有优先权,同时在HTTP1.0浏览器Expires生效。
不仅仅是图片
长久的Expires头应该包含任何不经常变化的组件,包括脚本、样式表和Flash组件。
修订文件名
如果我们将组件配置为可以由浏览器代理缓存,当这些组件改变时用户如何获得更新呢?当出现了Expires头时,直到过期为止一直会使用缓存的版本。
最有效的解决方案是修改其所有链接,这样,全新的请求将从原始服务器下载最新的内容。通常将版本号嵌在组件的文件名中。
总结
如果没有长久的Expires头,它仍然会存储在浏览器的缓存中。在后续请求中,浏览器会检查缓存并发现组件已经过期。为了提高效率,浏览器会发送一个GET请求。如果组件没有改变,原始服务器可以免于发送整个组件,而是发送一个很小的头,告诉浏览器可以使用其缓存的组件。
这些条件请求加起来,就是缓存节省的时间。