缓存对于web开发有重要作用,尤其是大负荷web系统开发中。

缓存分很多种:

  • 服务器缓存
  • 第三方缓存
  • 浏览器缓存。(代价最小,浏览器依赖的是客户端,几乎不耗费服务端的资源)

让浏览器做缓存需要给浏览器发送指定的Http头,告诉浏览器缓存多长时间,或者坚决不要缓存。

Expires (过期时间)

HTTP头信息Expires (过期时间)

属性是HTTP控制缓存的基本手段,这个属性告诉缓存器:相关副本在多长时间内是新鲜的。过了这个时间,缓存器就会向源服务器发送请求,检查文档是否被修改。几乎所有的缓存服务器都支持Expires (过期时间)属性;

大部分Web服务器支持你用几种方式设置Expires属性;
一般的:可以设计一个绝对时间间隔:基于客户最后查看副本的时间(最后访问时间)或者根据服务器上文档最后被修改的时间;

1. Expires头信息:

   对于设置静态图片文件(例如导航栏和图片按钮)特别有用;因为这些图片修改很少,你可以给它们设置一- 个特别长的过期时间,这会使你的网站对用户变得相应非常快;<br />他们对于控制有规律改变的网页也很有用,例如:你每天早上6点更新新闻页,你可以设置副本的过期时间也是这个时间,这样缓存服务器就知道什么时候去取一个更新版本,而不必让用户去按浏览器的“刷新"按钮。<br />      过期时间**头信息属性值只能是HTTP格式的日期时间**,其他的都会被解析成当前时间“之前”,副本会过期,记住:HTTP的日期时间必须是格林威治时间(GMT) ,而不是本地时间。举例:(Expires:Fri, 30 Oct 199814:19:41),所以使用过期时间属性一定要确认你的Web服务器时间设置正确,一个途径是通过网络时间同步协议(Network Time Protocol NTP)

1.1 局限

虽然过期时间属性非常有用,但是它还是有些局限,
1.牵扯到了日期,这样Web服务器的时间和缓存服务器的时间必须是同步的,如果有些不同步,要么是应该缓存的内容提前过期了,要
么是过期结果没及时更新。

1
2.过期时间设置的问题也不容忽视:如果你设置的过期时间是一个固定的时间, 如果你返回内容的时候又没有连带更新下次过期的时

间,那么之后所有访问请求都会被发送给源Web服务器,反而增加了负载和响应时间;

2. Cache-Control (缓存控制HTTP头信息)

HTTP 1.1介绍了另外-组头信息属性:Cache-Control响应头信息,
让网站的发布者可以更全面的控制他们的内容,并定位过期时间的限制。

![](002.浏览器缓存Cache-Control Expires/121e978c7a56260e66a21064b71f936d.png)
有用的Cache-Control响应头信息包括:

2.1 max-age=【秒】,

单位是秒:从请求时间开始到过期时间之间的秒数。

执行缓存被认为是最新的最长时间。类似于过期时间,这个参数是基于请求时间的相对时间间隔,而不是绝对过期时间,

2.2 s-maxage=【秒】

类似于max-age属性,除了他应用于共享(如:代理服务器)缓存

2.3 public

标记认证内容也可以被缓存,-般来说:经过HTTP认证才能访问的内容,输出是自动不可以缓存的;

2.4 no-cache

强制每次请求直接送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据的应用(不惜牺牲使用缓存的所有好处) ;

2.5 no-store

强制缓存在任何情况下都不要保留任何副本

   给静态资源(HTML文件,图片文件等)的Repsone加上Expires/Cache-Control Header是很有效的一招。如果HTTP Response中有Expires这样的Header的话,浏览器会Cache这个资源,理想状况下(注意,只是理想状况),在Expire Date之前,不会再发HTTP请求给Server要这个资源,不过Expires的值只能是一个固定日期,比如“Thu 27 Nov 200807:00:00 GMT",不能是一个类似“从现在开始之后10年”这样一个随机浮动的值,<br />如果要这样的效果,可以用Cache- Control这样的Header,如果HTTP Response中有这样的Header:"Cache-Control:max-age =100",表示这个资源在cache中的最大寿命是100秒。一般说来这种静态文件永远不应该过期,如果真的要给这个Cache加上-个期限,那我希望是一 一万年, "Cache-Control:max-age = 315360000000”,其实就应该给Expires设-个永远不会过期的时间,<br />

比如你现在有-个文件叫ogo.gif, 需要用一个新的logo的时候,

你不要去覆盖原来的文件,而把新的logo存成logo* v2.gif, 让相关网页引用新的logo* v2.gif, 这样可以让新老网页同时工作,实在犯不上为了节省存储空间覆盖原有文件

3. Last-Modified/If-Modifed-Since

有些数据随时都在变化。CNN.com 的主页经常几分钟就更新。另一方面, Goegle.com 的主页几个星期才更新-次(当他们上传特殊的假日logo,或为一个新服务作广告时)。Web 服务是不变的:通常服务器知道你所请求的数据的最后修改时间,并且HTTP为服务器提供了一种将最近修改数据连同你请求的数据一同发送的方法。

如果你第二次(或第三次,或第四次)请求相同的数据,你可以告诉服务器你上一次获得的最后修改日期:在你的请求中发送一个if-Modified-Since头信息,它包含了上一次从服务器连同数据所获得的日期。如果数据从那时起没有改变,服务器将返回一个特殊的HTTP状态代码304,这意味着“从上一次请求后这个数据没有改变”。这一点有何进步呢?当服务器发送状态编码304时,不再重新发送数据。您仅仅获得了这个状态代码。所以当数据没有更新时,你不需要一次又一次地下载相同的数据;服务器假定你有本地的缓存数据。

![](002.浏览器缓存Cache-Control Expires/b2b3fa3987549727974e2f316d693307.png)

所有现代的浏览器都支持最近修改(last-modifed)的数据检查。如果你曾经访问过某页, 一天后重新访问相同的页时发现它没有变化,并奇怪第二次访问时页面加载得如此之快一这就是原因所在。你的浏览器首次访问时会在本地缓存页面内容,当你第二次访问,浏览器自动发送首次访问时从服务器获得的最近修改日期。服务器简单地返回304:Not Modified (没有修改),因此浏览器就会知道从本地缓存加载页面。在这一点上,Web服务也如此智能。

4. ETag/If-None-Match

ETag是实现与最近修改数据检查同样的功能的另-种方法:没有变化时不重新下载数据。其工作方式是:服务器发送你所请求的数据的同
时,发送某种数据的hash (在ETag头信息中给出)。hash 的确定完全取决于服务器。
当第二次请求相同的数据时,你需要在If-None-Match:头信息中包含ETag hash,如果数据没有改变,服务器将返回304状态代码。与最近修改数据检查相同,服务器仅仅发送304状态代码;第二次将不为你发送相同的数据。

在第二次请求时,通过包含ETag hash,你告诉服务器:如果hash仍旧匹配就没有必要重新发送相同的数据,因为你还有上一次访问过的数据。

这几个http头可以作为meta标签发送到客户端,但是需要注意的是Http头中的设置优先级更高一些, 例如:

1
2
<meta http-equix="Expires" content=" Fri,30 Oct 199814:19:41" />
<meta http-equiv="Cache-Control" content="no-cache" />

总结

Expires/Cache-Control Header是控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。

只是Cache-Control比Expires可以控制的多-些,而且**Cache-Control会重写Expires的规则**。

Last-Modified/If-Modified-SinceETag/If-None-Match:

是浏览器发送请求到服务器后判断文件是否已经修改过,

  • 如果没有修改过就只发送一个304回给浏览器,告诉浏览器直接从自己本地的缓存取数据;
  • 如果修改过那就整个数据重新发给浏览器。