理清HTTP缓存的一些概念

之前的一篇文章只说了浏览器会有缓存,但使用f5刷新使用到协商缓存,而ctrl+f5则强制不使用缓存,在地址栏和回车则会同时使用本地缓存和协商缓存没有具体说明。本地缓存又叫强缓存,协商缓存又叫弱缓存。这篇文章补充一些这方面的东西。

cache

浏览器第一次请求时:

408483-20160525182843100-1556227104

浏览器后续在进行请求时:

408483-20160525182943272-204994049

 

从上图可以知道,浏览器缓存包含两种类型,即强缓存(也叫本地缓存)和协商缓存,浏览器在第一次请求发生后,再次请求时:

  • 浏览器在请求某一资源时,会先获取该资源缓存的header信息,判断是否命中强缓存(cache-control和expires信息),若命中直接从缓存中获取资源信息,包括缓存header信息;本次请求根本就不会与服务器进行通信;在firebug下可以查看某个具有强缓存资源返回的信息,例如本地firebug查看的一个强缓存js文件408483-20160525185916397-1208157783
  • 如果没有命中强缓存,浏览器会发送请求到服务器,请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),由服务器根据请求中的相关header信息来比对结果是否协商缓存命中;若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;否则返回最新的资源内容

强缓存与协商缓存的区别,可以用下表来进行描述:

获取资源形式 状态码 发送请求到服务器
强缓存  从缓存取  200(from cache) 否,直接从缓存取
协商缓存  从缓存取  304(not modified) 是,正如其名,通过服务器来告知缓存是否可用

缓存状态码

200 OK (from cache)  是浏览器没有跟服务器确认,直接用了浏览器缓存;

304 Not Modified 是浏览器和服务器多确认了一次缓存有效性,再用的缓存。

304 Not Modified 比 200 OK (from cache) 慢,指的是浏览器还向服务器确认了下 “If-Not-Modified”,才用的缓存。

缓存HTTP头信息

HTTP请求和响应的消息报头中,常见的与缓存有关的消息报头有:

4ltwyuXH

HTTP缓存机制

缓存行为主要由缓存策略决定,而缓存策略由内容拥有者设置。这些策略主要通过特定的HTTP头部来清晰地表达。

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

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

用户操作行为与缓存

TYHrxqQt

浏览器中的操作对缓存的影响:

  • 强制刷新 – 当按下ctrl+F5来刷新页面的时候, 浏览器将绕过各种缓存(本地缓存和协商缓存), 直接让服务器返回最新的资源;
  • 普通刷新 – 当按下F5来刷新页面的时候,浏览器将绕过本地缓蹲来发送请求到服务器, 此时, 协商缓存是有效的
  • 回车或转向 – 当在地址栏上输入回车或者按下跳转按钮的时候, 所有缓存都生效

本地缓存阶段

Expires

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

Cache-Control

Cache-Control:这个是http 1.1中为了弥补 Expires 缺陷新加入的。

对已缓存的内容进行控制:

Cache-control: public表示缓存的版本可以被代理服务器或者其他中间服务器识别。

Cache-control: private意味着这个文件对不同的用户是不同的。只有用户自己的浏览器能够进行缓存,公共的代理服务器不允许缓存。

Cache-control: no-cache意味着文件的内容不应当被缓存。这在搜索或者翻页结果中非常有用,因为同样的URL,对应的内容会发生变化。

其他相关控制字段:

max-age: 指定缓存过期的相对时间秒数,max-ag=0或者是负值,浏览器会在对应的缓存中把Expires设置为1970-01-01 08:00:00 。

s-maxage: 类似于max-age,只用在共享缓存上,比如proxy.

public: 通常情况下需要http身份验证的情况,响应是不可cahce的,加上public可以使它被cache。

no-cache: 强制浏览器在使用cache拷贝之前先提交一个http请求到源服务器进行确认。这对身份验证来说是非常有用的,能比较好的遵守 (可以结合public进行考虑)。它对维持一个资源总是最新的也很有用,与此同时还不完全丧失cache带来的好处),因为它在本地是有拷贝的,但是在用之前都进行了确认,这样http请求并未减少,但可能会减少一个响应体。

no-store: 告诉浏览器在任何情况下都不要进行cache,不在本地保留拷贝。

must-revalidate: 强制浏览器严格遵守你设置的cache规则。

proxy-revalidate: 强制proxy严格遵守你设置的cache规则。

用法举例: Cache-Control: max-age=3600, must-revalidate

cache:使用本地缓存,不发生请求。

协商缓存阶段

Last-Modified & if-modified-since

Last-Modified与If-Modified-Since是一对报文头,属于http 1.0。

last-modified是WEB服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间。

ETag & If-None-Match

ETag与If-None-Match是一对报文,属于http 1.1。

ETag可以用来解决这种问题。ETag是一个文件的唯一标志符。就像一个哈希或者指纹,每个文件都有一个单独的标志,只要这个文件发生了改变,这个标志就会发生变化。

ETag机制类似于乐观锁机制,如果请求报文的ETag与服务器的不一致,则表示该资源已经被修改过来,需要发最新的内容给浏览器。

同时使用这两个报文头,在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,如都与服务器的相符,服务器返回304,否则,发送最新内容给浏览器。

Etag/lastModified过程如下

1.客户端请求一个页面(A)。

2.服务器返回页面A,并在给A加上一个Last-Modified/ETag。

3.客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。

4.客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。

5.服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。

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

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

1、一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;

2、某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);

3、某些服务器不能精确的得到文件的最后修改时间。

其他标签

Content-Length:尽管并没有在缓存中明确涉及,Content-Length头部在设置缓存策略时很重要。某些软件如果不提前获知内容的大小以留出足够空间,则会拒绝缓存该内容。

Vary:缓存系统通常使用请求的主机和路径作为存储该资源的键。当判断一个请求是否是请求同样内容时,Vary头部可以被用来提醒缓存系统需要注意另一个附加头部。它通常被用来告诉缓存系统同样注意Accept-Encoding头部,以便缓存系统能够区分压缩和未压缩的内容。

参考:

http://www.cnblogs.com/wonyun/p/5524617.html

http://imweb.io/topic/55c6f9bac222e3af6ce235b9


关注我

我的微信公众号:前端开发博客,在后台回复以下关键字可以获取资源。

  • 回复「小抄」,领取Vue、JavaScript 和 WebComponent 小抄 PDF
  • 回复「Vue脑图」获取 Vue 相关脑图
  • 回复「思维图」获取 JavaScript 相关思维图
  • 回复「简历」获取简历制作建议
  • 回复「简历模板」获取精选的简历模板
  • 回复「加群」进入500人前端精英群
  • 回复「电子书」下载我整理的大量前端资源,含面试、Vue实战项目、CSS和JavaScript电子书等。
  • 回复「知识点」下载高清JavaScript知识点图谱

每日分享有用的前端开发知识,加我微信:caibaojian89 交流