一文读懂HTTP缓存机制

http缓存机制

一句话概况:本地缓存请求到的资源,后续请求尽量直接复用这些资源,减小Http请求,从而显著提升网站和应用程序的性能。web

那么何时缓存资源到本地?缓存资源何时过时?什么状况下使用这些缓存的资源呢?本文就带着这三个问题开始展开。算法

HTTP缓存机制流程

从流程中能够看到,浏览器发起资源请求后,大体有三部分:强缓存校验、协商缓存校验、资源请求。本文主要讲解强缓存和协商缓存模块,资源请求部分就是正常的一次HTTP交互过程,但值得注意的是:

由于通常只有GET请求才会被缓存,因此这里泛指通常的GET资源请求。浏览器

强缓存

不须要额外向服务端发送请求,直接使用本地缓存。在Chrome浏览器中本地强缓存分为两类,一类是disk cache,一类是memory cache,查看devtools中的Networks会看到请求状态为200,而且后面跟着from disk cachefrom memory cache的请求就是使用了强缓存,以下面两个图。缓存

本人也还没有了解Chrome浏览器如何控制两种强缓存,故不展开了,以避免误导读者,但愿能有高手指出!!!!这里放上找到的Chrome官方文档中的描述,其大致意思是两种强缓存策略与渲染进程的生命周期有关,渲染进程的周期又大体与tab选项卡相对应:服务器

Chrome employs two caches — an on-disk cache and a very fast in-memory cache. The lifetime of an in-memory cache is attached to the lifetime of a render process, which roughly corresponds to a tab. Requests that are answered from the in-memory cache are invisible to the web request API.性能

是否使用强缓存由HTTP的三个头部字段来控制:ExpiresPragmaCache-Control网站

Expires

Exipres字段是Http/1.0中的字段,其优先级在三个缓存控制字段中最低。代理

如图所示,响应头中Expires的值是一个时间戳,发起请求时,若是本地系统时间在这个时间戳以前,则缓存有效,不然缓存失效,进入协商缓存。若该响应头中Expires设置为无效的日期,好比 0, 则表明着过去的日期,即该资源已通过期。code

Cache-Control

Cache-ControlHTTP/1.1 中规定的通用头部字段,经常使用属性以下:

  • no-store:禁止使用缓存,每次请求都去服务端拿最新的资源;
  • no-cache:不使用强缓存,直接进入协商缓存模块,向服务端请求校验资源是否“新鲜”;
  • private:私有缓存,中间代理服务端不可缓存资源
  • public:公共缓存,中间代理服务端能够缓存资源
  • max-age:单位:秒,缓存的最长有效时间。其起始时间为缓存时响应头中的Date字段,即有效期到responseDate + max-age,发起请求时超过该时间则缓存过时。
  • must-revalidate:缓存一旦过时,则必须从新向服务端验证。

Pragma

PragmaHTTP/1.0 中规定的通用头部字段,用于向后兼容只支持 HTTP/1.0 协议的缓存服务端。这个字段只有一个值:no-cache,其表现行为与Cache-Control: no-cache一致,可是HTTP的响应头没有明肯定义这个属性,因此它不能拿来彻底替代HTTP/1.1中定义的Cache-control头。cdn

若是PragmaCache-Control 两个字段同时存在,Pragma的优先级大于Cache-Control

协商缓存

当强缓存过时或者请求头字段设置不走强缓存,好比Cache-Control:no-cachePragma:no-cache,则进入协商缓存部分。协商缓存涉及两对头部字段,分别是Last-Modified/If-Modified-Since、和ETag/If-None-Match

若请求头中携带If-Modified-SinceIf-None-Match字段,则会发起去服务端校验资源是否有变化,若是有变化,则未命中缓存,服务端返回200,浏览器计算响应体资源是否缓存并使用资源;若是未变换,则命中缓存,返回304,浏览器根据响应头更新缓存头部信息,延长有效期,并直接使用缓存。

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since的值是资源修改时间。第一次请求资源时,服务端将资源的最后修改时间放到响应头的 Last-Modified 字段中,第二次请求该资源时,浏览器会自动将该资源上一次响应头中的Last-Modified的值放到第二次请求头的If-Modified-Since字段中,服务端比较服务端资源的最后一次修改时间和请求头中的If-Modified-Since 的值,若是相等,则命中缓存返回 304,不然,返回200。

ETag/If-None-Match

ETag/If-None-Match 的值是一串hash值(hash算法不统一),是资源的标识符,当资源内容发生变化,其hash值也会改变。其过程与上面的类似,不过服务端是比较服务端资源的hash值和请求头中的If-None-Match的值,但比较方式有所区别,由于ETag有两种类型:

  • 强校验:资源hash值具备惟一性,一旦变化则hash也变化。
  • 弱校验:资源hash值以W/开头,若资源变化较小,则一样可能命中缓存。

例以下面这样:

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4" ETag: W/"0815"

二者区别

  1. ETag/If-None-Match优先级比Last-Modified/If-Modified-Since高;
  2. Last-Modified/If-Modified-Since有个1S问题,即服务端在1S内修改文件,且再次受到请求时,会错误的返回304

代理服务缓存

VaryHTTP/1.1中的一个头字字段,其值为请求头中的字段,如上图中的 Accept-Encoding,能够是多个,以逗号分割,其记录了代理服务器返回资源参考了哪些请求头字段。代理服务器拿到源服务器的响应报文,会根据 Vary 里的字段列表,缓存不一样版本的资源。当有资源请求再次访问时,代理服务器会分析请求头字段,返回正确的版本。

总结

在实际应用过程,对一些更新不频繁的资源合理使用缓存机制,能够有效提升系统的响应速度,提升用户体验。

相关文章
相关标签/搜索