liujinyu

前言:“学习提升往往是打破思维壁垒的过程”,缓存策略是一个封闭的既成事实?还是只是一个约定规则?客户度的事被浏览器做了多少?服务端也是如此么? 还是只是被框架阻拦了思维,只是框架替你做了,如果进入底层,一些要自己写,那这些只是规则?是否也能被改写?

 

(阅读文章前,先理解观点1,带着观点看文章)

【观点1】:缓存规则是一个客观事实么?不,对于服务端而言,它可以只是一个主观设置的规则。

 

 

一、缓存原理

=======================

1、通过地址栏的链接访问不会使用缓存(也就是入口文件必定访问服务器),入口文件中引入的文件资源才会被缓存。

2、缓存是浏览器和服务器端的游戏,判断条件只有【两点】: 

          1、【当前缓存是否过期?】  不管过没过期(过期了继续使用),如文件没有改变,返回304,启用缓存;

          2、【服务器中的文件是否有改动?】  即便没过期,但是改动了,也会返回200,并送上新文件与新修改日期

 

二、如何实现缓存

========================

1、【缓存期限】:请求头中携带期限字段,有两种字段方式(以前还有一种pragma,优先级最高,不过慢慢抛弃了)

    【Expires】:直接标明过期时间,绝对时间;

    【Cache-Control(max-age)】:max-age存放是一个时间段,相对时间。优先级高,并且排挤Expires,Cache-Control配置了max-age时Expires失效。

 

2、【文件变动】: 判断文件变动有两种标识方式 ETag 、Last-modified

ETag】:响应头返回ETag标识(hash值),下次请求头携带If-None-Match,服务端对比两值,相等则返回304,不等则返回200,新资源新ETag。

(也可以用If-Match,区别是如果不一致,返回状态码412)

Last-modified】:响应头返回最后修改时间,下次请求头携带 If-Modified-Since,服务端对比两值,相等则返回304,否则返回200并带上新的Last-modified。

(也可以用If-Unmodified-Since,区别是如果时间不一致,返回状态码412)

 

三、如何通过 Cache-Control 支配缓存(Cache-Control 在请求头与响应头中都有使用)

===============================================================

使用示例:Cache-Control: must-revalidate, max-age=60

 

请求头与响应头都可使用

1、no-cache:还是有缓存的,只不过客户端(代理服务器)每次都要先向服务器发起请求,验证过了再决定是否使用缓存

2、no-store:完全不使用缓存,每次都向服务器获取新资源

3、max-age=60:客户端向服务器索要有效期60秒的资源 \ 服务器告知客户端该资源60秒内为新鲜,不许再向服务器发起请求(跟第一次请求时间对比)。max-age<=0,立即过期的响应(记为陈旧状态),向server发起请求,资源是否修改 ,返回200 ,或304。

 

只用在响应头中的使用

1、public:任何情况都要缓存该资源(如果定义了max-age,可以不用再定义public,意义是一样的),可以和no-cache结合使用

2、private[=“field-name”]:返回文件中全部或部分(field-name为指定的部分内容)仅开放给某些用户(服务器指定的share-user,如代理服务器)做缓存使用,其他用户不能缓存

3、must-revalidate:资源还在max-age的缓存期内则直接使用缓存,过期后必须到服务器验证

 

四、强缓存与协商缓存

===============================================================================

chrome、safari中状态码为200的时候也是有可能读缓存的,而且还是强缓存,而火狐没有这样的策略,还是走协商缓存,返回304,这也是chrome更快的原因。

 

1、200 ok    从服务器下载资源

2、200 okfrom memory cach 从内存获取缓存,一般为脚本、字体、图片,关闭浏览器会被释放

3、200 okfrom disk cache从磁盘获取缓存,一般为css,关闭浏览器不会消失

 

 

样式表一般在磁盘中,不会缓存到内存中去,因为css样式加载一次即可渲染出网页。但是脚本却可能随时会执行,如果脚本在磁盘当中,在执行该脚本需要从磁盘中取到内存当中来,这样的IO开销是比较大的,有可能会导致浏览器失去响应。

 

注:200 ok 中标注的是文件真实大小,而304 Not Modified  中标注的有可能(分浏览器)是通信报文的大小,不是文件的大小。

 

下面对比同一个文件app.js,chrome 和火狐对比

======================

1、chrome 中再General中标注200(from memory cache)状态,响应头中状态还是304

 

 

 

 

 

 

 

 

=====================

2、火狐:看缓存是否命中很方便

 

 

 

 

 

 

————————

 

 

下表是在不同浏览器中,cache-control与etag作用的罗列

 

Chrome

Safari

Firefox

QQ浏览器

max-age=0

200

200

200

200

max-age=60

200 (from memory cache)

200 (来源内存缓存)

200

200

max-age=60

ETag

200 (from memory cache)

200 (来源内存缓存)

304

304

max-age=60no-cache

ETag

304

304

304

304

总结:

1、Chrome,Safari浏览器中,有200 (读取内存缓存)策略,只要响应头出现 catch-control:max-age=60,在60秒内就一定强读缓存。如果想要走304验证缓存,便加上no-cache

2、在chrome中,\'max-age=5’失效后,再次请求可能不是200,而是304,因为再请求已经有了If-None-Match、If-Modified-Since标记,这时候就看服务器的策略了,如果服务器端验证了文件其实并没有修改,允许重用已过期缓存,则返回304,并在响应头中携带新的过期时间。显示的过程是:第一次200,5秒内200(from memory cache),5秒后304,再接来下5秒继续200(from memory cache)

 

QA

1、带if标记(如If-None-Match、If-Modified-Since),浏览器就一定有缓存么,万一浏览器没有缓存怎么办

A:当浏览器在请求头加上if标识,则代表已经有缓存

 

1、must-revalidate, max-age=5中,must-revalidate意义何在,没有它,60秒到期后,也会去服务端请求啊

A:这是针对缓存服务器的。缓存服务器,可以通过配置,提供一些陈旧的对象,以提高性能。如果原始服务器希望缓存能遵守过期信息,可以在相应头部添加cache-control: must-revalidate,告诉缓存,过期后,在没有跟服务器校验的情况下,不能提供这个对象的旧版本,如果服务器不可用,那么缓存服务器必须返回504错误(网关超时错误:网关或代理服务器,没有及时从上游服务器收到请求)

 

 

2、200不使用缓存么?304就是调用缓存么?怎么确定命中缓存?代理服务器的缓存呢?

A:200不一定就是获取数据,有可能是读取内存\磁盘缓存,304代表转向

 

 

请求头部有max-stale,表示可接受过期的响应

 

 

 

缓存max-agemax-stale详解

 

Html5应用程序缓存(Cache manifest)

浏览器缓存 - 如何强制浏览器读取缓存 

分类:

技术点:

相关文章: