s-maxage=[秒] ― 类似于max-age属性,除了他应用于共享(如:代理服务器)缓存
public ― 标记认证内容也可以被缓存,一般来说: 经过HTTP认证才能访问的内容,输出是自动不可以缓存的;
no-cache ― 强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据的应用(不惜牺牲使用缓存的所有好处);
no-store ― 强制缓存在任何情况下都不要保留任何副本
must-revalidate ― 告诉缓存必须遵循所有你给予副本的新鲜度的,HTTP允许缓存在某些特定情况下返回过期数据,指定了这个属性,你高速缓存,你希望严格的遵循你的规则。
proxy-revalidate ― 和 must-revalidate类似,除了他只对缓存代理服务器起作用
举例:
Cache-Control: max-age=3600, must-revalidate
如果你计划试用Cache-Control属性,你应该看一下这篇HTTP文档,详见参考和深入阅读;
校验参数和校验
在Web缓存如何工作: 我们说过:校验是当副本已经修改后,服务器和缓存之间的通讯机制;使用这个机制:缓存服务器可以避免副本实际上仍然足够新的情况下重复下载整个原件。
校验参数非常重要,如果1个不存在,并且没有任何信息说明保鲜期(Expires或Cache-Control)的情况下,缓存将不会存储任何副本;
最常见的校验参数是文档的最后修改时间,通过最后Last-Modified头信息可以,当一份缓存包含Last-Modified信息,他基于此信息,通过添加一个If-Modified-Since请求参数,向服务器查询:这个副本从上次查看后是否被修改了。
HTTP 1.1介绍了另外一个校验参数: ETag,服务器是服务器生成的唯一标识符ETag,每次副本的标签都会变化。由于服务器控制了ETag如何生成,缓存服务器可以通过If-None-Match请求的返回没变则当前副本和原件完全一致。
所有的缓存服务器都使用Last-Modified时间来确定副本是否够新,而ETag校验正变得越来越流行;
所有新一代的Web服务器都对静态内容(如:文件)自动生成ETag和Last-Modified头信息,而你不必做任何设置。但是,服务器对于动态内容(例如:CGI,ASP或数据库生成的网站)并不知道如何生成这些信息,参考一下编写利于缓存的脚本章节;
创建利于缓存网站的窍门
除了使用新鲜度信息和校验,你还有很多方法使你的网站缓存友好。
保持URL稳定: 这是缓存的金科玉律,如果你给在不同的页面上,给不同用户或者从不同的站点上提供相同的内容,应该使用相同的URL,这是使你的网站缓存友好最简单,也是 最高效的方法。例如:如果你在页面上使用 "/index.html" 做为引用,那么就一直用这个地址;
使用一个共用的库存放每页都引用的图片和其他页面元素;
对于不经常改变的图片/页面启用缓存,并使用Cache-Control: max-age属性设置一个较长的过期时间;
对于定期更新的内容设置一个缓存服务器可识别的max-age属性或过期时间;
如果数据源(特别是下载文件)变更,修改名称,这样:你可以让其很长时间不过期,并且保证服务的是正确的版本;而链接到下载文件的页面是一个需要设置较短过期时间的页面。
万不得已不要改变文件,否则你会提供一个非常新的Last-Modified日期;例如:当你更新了网站,不要复制整个网站的所有文件,只上传你修改的文件。
只在必要的时候使用Cookie,cookie是非常难被缓存的,而且在大多数情况下是不必要的,如果使用cookie,控制在动态网页上;
减少试用SSL,加密的页面不会被任何共享缓存服务器缓存,只在必要的时候使用,并且在SSL页面上减少图片的使用;
使用可缓存性评估引擎,这对于你实践本文的很多概念都很有帮助;
编写利于缓存的脚本
脚本缺省不会返回校验参数(返回Last-Modified或ETag头信息)或其他新鲜度信息(Expires或Cache-Control),有些动态脚本的确是动态内容(每次相应内容都不一样),但是更多(搜索引擎,数据库引擎网站)网站还是能从缓存友好中获益的。
一般说来,如果脚本生成的输出在未来一段时间(几分钟或者几天)都是可重复复制的,那么就是可缓存的。如果脚本输出内容只随URL变化而变化,也是可缓存的;但如果输出会根据cookie,认证信息或者其他外部条件变化,则还是不可缓存的。
最利于缓存的脚本就是将内容改变时导出成静态文件,Web服务器可以将其当作另外一个网页并生成和试用校验参数,让一些都变得更简单,只需要写入文件即可,这样最后修改时间也有了;
另外一个让脚本可缓存的方法是对一段时间内能保持较新的内容设置一个相对寿命的头信息,虽然通过Expires头信息也可以实现,但更容易的是用Cache-Control: max-age属性,它会让首次请求后一段时间内缓存保持新鲜;
如果以上做法你都做不到,你可以让脚本生成一个校验属性,并对 If-Modified-Since 和/或If-None-Match请求作出反应,这些属性可以从解析HTTP头信息得到,并对符合条件的内容返回304 Not Modified(内容未改变),可惜的是,这种做法比不上前2种高效;
其他窍门:
尽量避免使用POST,除非万不得已,POST模式的返回内容不会被大部分缓存服务器保存,如果你发送内容通过URL和查询(通过GET模式)的内容可以缓存下来供以后使用;
不要在URL中加入针对每个用户的识别信息:除非内容是针对每个用户不同的;
不要统计一个用户来自一个地址的所有请求,因为缓存常常是一起工作的;
生成并返回Content-Length头信息,如果方便的话,这个属性让你的脚本在可持续链接模式时:客户端可以通过一个TCP/IP链接同时请求多个副本,而不是为每次请求单独建立链接,这样你的网站相应会快很多;
具体定义请参考实现章节。
常见问题解答
让网站变得可缓存的要点是什么?
好的策略是确定那些内容最热门,大量的复制(特别是图片)并针对这些内容先部署缓存。