浏览器缓存

一、缓存协商

在使用缓存的时候,我们不但需要在Web服务器上使用缓存,同时也尽可能地让Web站点的内容缓存在用户的浏览器中,特别是一些长期不会出现更改的静态文件,这样将在一定程度减少了服务器的计算机开销,而且也避免了有些内容由于不必要的传输而带来的带宽浪费。

通过IE的选项打开IE的缓存目录,可以看到:

browsercache

其中有Internet地址,截止期限( Expires ),上次修改时间( Last-Modified )等等文件信息。

对于Firefox浏览器,它存储缓存文件的方式有所不同。并不像IE那样将每个文件独立存储,而是采用二进制文件的方式来存储和管理缓存文件。

firefoxcache

可以看到,Firefox浏览器在使用磁盘来存储缓存文件的同时,还使用了内存,它将命中率较高的缓存内容同时也装入内存中,这样浏览器在查找缓存的时候,将先在高速内存中查找,如果内存中没有需要的缓存,便前往磁盘缓存目录中继续查找,这种从内存到磁盘的多级缓存机制有时会带来更快的缓存加载速度。

由于浏览器的缓存内容是存放在浏览器本地的,而内容由Web服务器生成,因此两者需要一种沟通机制来进行缓存协商。协商的过程很容易理解。首先,当浏览器向Web服务器请求一些内容时,Web服务器需要告诉浏览器哪些内容可以被缓存,一旦浏览器知道某个内容可以缓存后,下次当浏览器需要请求这个内容时,它便不会直接向服务器请求完整内容,而是询问服务器是否可以使用本地的缓存,服务器在收到浏览器的询问后需要作出果断的回应,到底是允许浏览器使用本地缓存还是将最新的内容传回浏览器。

这里有两种协商的方法:Last-ModifiedETag

1. Last-Modified :

“”"
The Last-Modified entity-header field indicates the date and time at which the origin server believes the variant
was last modified.
“”"

事实上动态内容一般不存在传统意义上的最后修改时间,静态文件可以通过stat()系统调用获得它在物理文件系统的最后修改时间,一般Web服务器会为静态文件的HTTP响应头自动生成最后修改时间。在HTTP协议中规定Last-Modified使用的是GMT时间。其流程大致为:

webcache

If-Modified-Since

“”"
The If-Modified-Since request-header field is used with a method to make it conditional: if the requested
variant has not been modified since the time specified in this field, an entity will not be returned from the server;
instead, a 304 (not modified) response will be returned without any message-body.
“”"

而If-Modified-Since的值正是Web服务器返回的Last-Modified,当Web服务器看到有If-Modified-Since,则根据Web服务器的配置来决定是否返回请求的内容还是返回304状态。

2. ETag

ETag的协商方式与上述的方式非常类似,但它采用的不是最后修改时间,而是一串编码来标记内容,这串内容称为ETag。一个原则是,如果一个内容的ETag没有变化,那么这个内容也一定没有更新。在HTTP/1.1并没有规定ETag的具体格式和计算方法,也就是说,Web服务器可以自由定义ETag的格式和计算方法,比如一种简单的方法是对文件内容计算md5值作为ETag。其流程与Last-Modified相似:

etag当浏览器在下次请求的时候,在HTTP请求头中附加”If-None-Match”的时候(值为ETag的内容),服务器就需要重新计算这个内容的ETag值,并与HTTP请求中的ETag进行比较。如果相同就返回304状态码,不同的话就将最新的内容返回给浏览器。

二、浏览器缓存截止

HTTP中有一个标记,Expires(IE缓存目录见到的截止期限):
“”"
The Expires entity-header field gives the date/time after which the response is considered stale. A stale cache
entry may not normally be returned by a cache (either a proxy cache or a user agent cache) unless it is first validated
with the origin server (or with an intermediate cache that has a fresh copy of the entity).
The presence of an Expires field does not imply that the original resource will change or cease to exist at, before,
or after that time.
“”"
它告诉浏览器该内容在何时过期,暗示浏览器在该内容过期之前不需要再询问服务器,而直接使用本地缓存即可。这样的好处显而易见,一旦浏览器丝毫不用请求服务器,那将完全节省了带宽和服务器处理等开销,可谓皆大欢喜。

对于浏览器请求页面有三种方式:

  • Ctrl+F5 : 这种方式叫强制刷新,它使得网页以及其中的所有组件都直接向Web服务器发送请求,并且不使用缓存协商,这样的目的是获取所有页面内容的最新版本。
  • F5 : 这种方式便是一般的刷新,我们经常使用,它等同于单击浏览器的刷新按钮。它允许浏览器在请求中附加必要的缓存协商,但不允许浏览器直接使用本地缓存,也就是说,它能够让 Last-Modified 发挥效果,但是会无视 Expires。
  • 单击浏览器地址栏的“转到”按钮、回车、通过超链接打开网页 : 这种方式允许浏览器以最少的请求来获取网页的数据,浏览器会对所有没有过期的内容直接使用本地缓存,所以,Expires 标记只对这种方式有效。

还存在一个问题,通过 Expires 指定的过期时间,是来自于Web服务器的系统时间,如果用户本地的时间和服务器时间不一致的话,那一定会影响到本地缓存的有效期检查,没有人能够保证到用户本地时间与Web服务器严格一致。幸运的是,HTTP/1.1中还有一个标记用于弥补 Expires 的不足,那就是 Cache-Control ,它的格式如下:

Cache-Control: max-age=<second>

max-age指定了缓存过期的相对时间,单位是秒,并且这个时间是相对于浏览器本地时间而言。目前主流的浏览器都将 HTTP/1.1 作为首选,所以当HTTP响应头中同时含有 Expires 和 Cache-Control 时,浏览器会优先考虑 Cache-Control。对于没有 Cache-Control 的情况,浏览器则会服从 Expires 的指示。

来源:

  • 《构建高性能Web站点》
  • RFC2616
This entry was posted in Web. Bookmark the permalink.

3 Responses to 浏览器缓存

  1. vonbo says:

    你很能写啊~

  2. Stephen says:

    你应该说我很能copy :)

  3. ljian says:

    到此一游

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>