HTTP缓存

80 阅读4分钟

HTTP缓存

缓存机制

浏览器在发送请求前,会根据HTTP响应头部信息进行强缓存判定是否从缓存中直接获取资源。如果没有匹配上强缓存规则,则开始发送请求到服务器,进行协商缓存判定是否从缓存中获取资源,如果前两步都没有匹配成功,则开始从服务器获取资源。

强缓存

当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是ExpiresCache-Control,其中Cache-Control优先级比Expires

注:第一次请求,不存在缓存标识,会直接向服务器发送请求

Expires是HTTP1.0的产物,现如今已经基本放弃使用Expires(本文暂不讨论)

Cache-Control

用于控制网页缓存的字段,规则可以一个或者多个,依次进行判定,主要取值有:

  • public:所有内容都会被缓存(客户端和代理服务器都可缓存)
  • private (默认值) :所有内容只有客户端可以换成。 (对于前端而言,private和public基本一样)
  • max-age=xxx:缓存内容将在xxx秒后过期
  • no-cache:客户端缓存内容,但是否使用缓存需要经过协商缓存的验证来决定
  • no-store:所有内容都不会被缓存,既不强缓存,也不协商缓存
  • must-revalidate:客户端缓存过期前使用缓存,过期后则需要去服务器进行相对应的验证 (与no-cache类似,但更严格,强制意味更明显)

关于max-age=0、no-cache和must-revalid的区别

max-age=0 表示一个立即过期的响应(直接标记为陈旧状态)

no-cache 表示浏览器强制进行新鲜度验证(不管是否新鲜),待服务器确认新鲜度以后,再使用缓存

must-revalidate 只有在缓存过期之后,浏览器才会去服务器验证缓存的新鲜度

这样看来,似乎max-age=0、no-cache和must-revalid基本上是可以画等号了,但是要注意细微的差别

在执行must-revalidate时,若浏览器第二次去请求服务器来做新鲜度验证,结果服务器挂了,无法访问,那么缓存需要返回一个504 Gateway Timeout的错误

而如果是no-cache,当验证新鲜度时,服务器挂了,则会照样使用本地缓存显示给用户(有的总比没的好,当然有可能显示的就是旧的文档了)

结论:must-revalidate用在对事务要求比较严苛的情况下使用(比如支付)

缓存位置

主要有硬盘缓存from disk cache和内存缓存from memory cache两种

一般js文件和图片等文件解析后存放在内存缓存中;css文件则会存放在硬盘缓存中

浏览器读取缓存的顺序为memory –> disk

内存缓存from memory cache的特点

  • 快速读取
  • 时效性:一旦进程关闭,该进程的内存会被清空

硬盘缓存from disk cache的特点

  • 写入硬盘文件
  • 进行I/O操作
  • 速度比内存缓存慢

协商缓存

协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要分为两种情况:

  • 协商缓存生效,返回304和Not Modified
  • 协商缓存失效,返回200和请求结果

控制协商缓存的字段分别有:Last-Modified / If-Modified-SinceEtag / If-None-Match其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高,同时存在则只有Etag / If-None-Match生效

Last-Modified / If-Modified-Since

Last-Modified是服务器响应请求时,返回改资源文件的最后修改时间

If-Modified-Since则是客户端再次请求服务器时,携带上次请求时返回的Last-Modified值到服务器进行比对,如果服务器上的资源最后修改时间与请求带回来的If-Modified-Since值不匹配,则重新返回资源,状态码为200;否则返回304,代表缓存文件可继续被使用。

缺点:

  • 保存的时间是以秒为单位的,1秒内多次修改是无法捕捉到的
  • 各机器读取到的时间不一致,就有出现误差的可能性

Etag / If-None-Match

Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。

客户端再次发送请求时,会将上一次服务器返回的Etag值放在If-None-Match里,如果服务器上改资源的Etag与客户端If-None-Match里带来的值不一致,则重新返回资源以及新的Etag,状态码为200;否则返回304,客户端使用缓存文件即可。

优缺点:

  • 性能不如Last-Modified / If-Modified-Since
  • 精度高于Last-Modified / If-Modified-Since