浏览器缓存机制

HTTP缓存机制

当一个用户发起一个静态资源请求的时候,浏览器会通过以下几步来获取资源:

  1. 200 from memory cache
    不访问服务器,直接读缓存,从内存中读取缓存,此时的数据时缓存到内存中的,当页面被关闭以后,数据将不存在。
  2. 200 from disk cache
    不访问服务器,直接读缓存,从磁盘中读取缓存,当页面或浏览器关闭后,数据还是存在。
  3. 304 (Not Modified)
  • 缓存过期,但Last-ModifiedEtag验证资源有效,服务器返回304
  • 缓存需要强制验证,确定资源有效后,服务器返回304,如:Cache-Control:no-cach(这个设置规定缓存前必须先确定有效性)

具体描述:

  1. 本地缓存阶段:先在本地查找该资源,如果有发现该资源,而且该资源还没有过期,就使用这一个资源,完全不会发送http请求到服务器;
  2. 协商缓存阶段:如果在本地缓存找到对应的资源,但是不知道该资源是否过期或者已经过期,则发一个http请求到服务器,然后服务器判断这个请求,如果请求的资源在服务器上没有改动过,则返回304,让浏览器使用本地找到的那个资源;
  3. 缓存失败阶段:当服务器发现请求的资源已经修改过,或者这是一个新的请求(在本地缓存中没有找到资源),服务器则返回该资源的数据,并且返回200

协商缓存阶段

Last-Modified & if-modified-since

Last-ModifiedIf-Modified-Since是一对报文头,属于http 1.0
last-modified是WEB服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间。

ETag & If-None-Match

ETagIf-None-Match是一对报文,属于http 1.1
ETag是一个文件的唯一标志符,就像一个哈希或者指纹,每个文件都有一个单独的标志,只要这个文件发生了改变,这个标志就会发生变化,如果请求资源的ETag与服务器的不一致,则表示该资源已经被修改过来,需要发最新的内容给浏览器。

Etag/lastModified过程如下:

  1. 客户端请求一个页面(A)。
  2. 服务器返回页面A,并在给A加上一个Last-Modified/ETag。
  3. 客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。
  4. 客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
  5. 服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。

注意:通过If-Modified-SinceIf-Match判断资源是否修改,如未修改则返回304,发生了一次请求,但请求内容长度为0,节省了带宽,如果有多台负载均衡的服务器,不同服务器计算出的Etag可能不同,这样就会造成资源的重复加载。

Etag主要为了解决Last-Modified无法解决的一些问题:

  1. 一些文件如果改变后,又改回来了,Last-Modified会认为文件修改过,但其实它是没有变化的,Etag就不会判定它变化了
  2. If-Modified-Since能检查到文件的变化是秒级别的,但如果一个文件1秒内变化了好几次,If-Modified-Since就检测不出来,这时需要Etag检测
  3. 某些服务器不能精确的得到文件的最后修改时间

本地缓存阶段

ExpiresCache-Control是需要在服务器端配置的

Expires

指定缓存到期GMT的绝对时间,如果设了max-age,max-age就会覆盖expires。如果expires到期需要重新请求。

缺陷:Expires受限于本地时间,如果修改了本地时间,可能会造成缓存失效

Cache-Control

Cache-Control:这个是http 1.1中为了弥补 Expires 缺陷新加入的,下面是常用的值:

  • no-cache:强制浏览器在使用cache之前,先提交一个http请求到源服务器进行确认资源是否有效,防止从缓存中获取的是无效的资源。虽然http请求并未减少,但返回的是一个空的请求体,这样相当于减少了一个响应体。
  • no-storeno-store规定了浏览器不缓存任何缓存,而no-cache只是不缓存无效(这里是无效不是过期)的资源。
    如下图:资源Expires已失效,也设置了no-cach,但浏览器还是缓存了过期的资源(304可以证明已缓存),因为服务器判断了If-Modified-Since,资源是没有改动过的,所以返回了304
  • max-age:指定多少秒后缓存过期,如Cache-Control: max-age=3600, must-revalidate(3600秒后过期)
  • must-revalidate: 强制浏览器严格遵守你设置的cache规则。
  • proxy-revalidate: 强制proxy严格遵守你设置的cache规则。

参考:

  1. 缓存策略
  2. 详解浏览器缓存机制与Apache设置缓存
  3. 由memoryCache和diskCache产生的浏览器缓存机制的思考