强缓存和协商缓存
2021年9月6日
14分钟阅读
0 次浏览
0 条评论
1 为什么要使用浏览器缓存 - 减少了冗余的数据传输,节省了流量 - 减少了服务器的负担,大大提升了网站的性能 - 加快了客户端加载网页的速度 - 更好的用户体验 2 浏览器缓存类型 浏览器缓存主要有两类:缓存协商和彻底缓存,也有称之为协商缓存和强缓存。 强缓存:强制缓存整体流程比较简单,就是在第一次访问服务器取到数据之后,在过期时间之内不会再去重复请求。实现这个流程的核...
1 为什么要使用浏览器缓存
-
减少了冗余的数据传输,节省了流量
-
减少了服务器的负担,大大提升了网站的性能
-
加快了客户端加载网页的速度
-
更好的用户体验
2 浏览器缓存类型
浏览器缓存主要有两类:缓存协商和彻底缓存,也有称之为协商缓存和强缓存。
强缓存:强制缓存整体流程比较简单,就是在第一次访问服务器取到数据之后,在过期时间之内不会再去重复请求。实现这个流程的核心就是如何知道当前时间是否超过了过期时间。
-
http1.0 强制缓存通过 Expires 响应头来实现
-
http1.1 强制缓存通过 Cache-Control 响应头来实现。
协商缓存:协商缓存与强制缓存的不同之处在于,协商缓存每次读取数据时都需要跟服务器通信,并且会增加缓存标识。在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。
-
http 1.0 last-Modified
-
Etag
3 强缓存( Cache-Control 和 Expires )
强缓存主要是采用响应头
中的 Cache-Control
和 Expires
两个字段进行控制的。
其中 Expires 是 HTTP1.0 中定义的,它指定了一个绝对
的过期时期。而 Cache-Control 是 HTTP1.1 时出现的缓存控制字段。由于 Expires 是 HTTP1.0 时代的产物,因此设计之初就存在着一些缺陷,如果本地时间和服务器时间相差太大,就会导致缓存错乱。
所以当这两个字段同时使用的时候,Cache-Control 的优先级会更高一点。
在请求头
中使用 Cache-Control 时,它可选的值有:
指令 | 说明 |
---|---|
no-cache | 使用代理服务器的缓存之前提交原始服务器验证,验证通过才能使用 |
no-store | 在客户端或是代理服务器都不缓存请求或响应的任何内容 |
max-age=[秒] | 告知服务器客户端可接受资源的存在最大时间 |
max-stale(=[秒]) | 可接受(代理服务器缓存的)过期资源,参数可省略 |
min-fresh=[秒] | 可接受(代理服务器缓存的)资源更新时间小于指定时间 |
no-transform | 代理服务器不可以更改媒体类型 |
only-if-cached | 客户端只接受已缓存的响应,若缓存不命中,则返回 504 错误 |
cache-extension | 自定义扩展值,若服务器不知别该指令,就直接忽略 |
在响应头
中使用 Cache-Control 时,它可选的值有:
指令 | 说明 |
---|---|
public | 表明该资源可以给多个用户使用 |
private(= name) | 该资源是私有资源,指定的用户可以使用的缓存 |
no-cache | 强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。 |
no-store | 在客户端或是代理服务器都不缓存请求或响应的任何内容 |
no-transform | 代理服务器不可以更改媒体类型 |
must-revalidate | 可缓存但必须再向源服务器进行请求确认 |
proxy-revalidate | 要求缓存服务器返回缓存的时候向源服务器进行请求确认 |
max-age=[秒] | 告知客户端该资源在规定时间内是新鲜的,无需向服务器确认 |
s-maxage=[秒] | 告知缓存服务该资源在规定时间内是新鲜的,无需向服务器确认 |
cache-extension | 自定义扩展值,若服务器不识别该指令,就直接忽略 |
可缓存性
public
:响应可以被任何对象(客户端、代理服务器等)缓存private
:只能被单个用户缓存,不能作为共享缓存no-cache
:使用缓存副本之前,需要将请求提交给原始服务器进行验证,验证通过才可以使用only-if-cached
:客户端只接受已缓存的响应,并且不向原始服务器检查是否有更新的拷贝
到期
max-age=<seconds>
:缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与Expires
相反,时间是相对于请求的时间s-maxage=<seconds>
:覆盖max-age
或者Expires
头,但是仅适用于共享缓存(比如各个代理),并且私有缓存中它被忽略max-stale[=<seconds>]
:表明客户端愿意接收一个已经过期的资源。可选的设置一个时间(单位秒),表示响应不能超过的过时时间min-fresh=<seconds>
:表示客户端希望在指定的时间内获取最新的响应
重新验证和重新加载
must-revalidate
:缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。proxy-revalidate
:与must-revalidate
作用相同,但它仅适用于共享缓存(例如代理),并被私有缓存忽略
其他
no-store
:彻底得禁用缓冲,本地和代理服务器都不缓冲,每次都从服务器获取no-transform
:不得对资源进行转换或转变。Content-Encoding
,Content-Range
,Content-Type
等HTTP
头不能由代理修改。
4 协商缓存 ( Last-Modified 和 Etag )
协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求还是从本地获取缓存的资源。如果服务端提示缓存资源未改动( Not Modified ),资源会被重定向到浏览器缓存
,这种情况下网络请求对应的状态码是 304
Last-Modified 和 If-Modified-Since
都是基于资源在服务器修改时间而验证缓存的过期机制
当客户端再次请求该资源的时候,会在其请求头
上附带上If-Modified-Since
字段(值为第一次获取请求资源时响应头
中返回的Last-Modified
值)。如果修改时间未改变则表明资源未过期,命中缓存,服务器就直接返回 304 状态码,客户端直接使用本地的资源。否则,服务器重新发送响应资源,从而保证资源的有效性。
Etag 和 If-None-Match
基于资源校验码(一般为md5值)而验证缓存的过期机制
当客户端再次请求该资源的时候,会在其请求头上附带上 If-None-Match
字段(值就是第一次获取请求资源时响应头中返回的 Etag
值),其值与服务器端资源文件的验证码进行对比,如果匹配成功直接返回 304
状态码,从浏览器本地缓存取资源文件。如果不匹配,服务器会把新的验证码放在请求头的 Etag
字段中,并且以 200
状态码返回资源。
需要注意的是当响应头中同时存在
Etag
和Last-Modified
的时候,会先对Etag
进行比对,随后才是Last-Modified
。
为什么既有last-modified又有Etag? 原因如下:
-
一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候,我们并不希望客户端认为这个文件被修改了,而重新请求该资源,而Etag是对文件的内容进行hash计算,如果文件内容没有发生改变,Etag也不会发生改变,客户端也不会重新请求该资源
-
某些文件修改非常频繁,比如在秒以下的时间内进行修改(比方说 1s 内修改了 N 次),
If-Modified-Since
能检查到的粒度时 s 级的,这种修改无法判断(或者说 UNIX 记录 MTIME只能精确到秒),这时候客户端可能会得到错误的资源 -
某些服务器不能精确得到的文件的最后修改时间
-
一般情况下
Last-Modified
已经足够,ETag
只在特定情况下才更有用,有时候前端发布文件不可能一秒发布好多次,而且Etag可能会给服务器带来更大的开销(使用了MD5加密算法),所以一般就用Last-Modified
就行,ETag
可以看作是对Last-Modified
的一个补充
所以利用Etag可以更准确的控制缓存,优先级也更加高。
Etag 的问题
相同的资源,在两台服务器产生的
Etag
是不是相同的,所以对于使用服务器集群
来处理请求的网站来说,Etag
的匹配概率会大幅降低。所在在这种情况下,使用Etag
来处理缓存,反而会有更大的开销。
5 静态资源的请求过程
第一次请求肯定是从服务器中请求多来的资源,而第一次的响应头
一般包含可强缓存的相关字段cache-control
,同时也包含了协商缓存的相关字段 etag
和 last-modified
;
当强缓存和协商缓存字段同时存在的时候,会按照以下步骤来请求资源
-
强缓存优先级 > 协商缓存优先级 强缓存和协商缓存同时存在,如果强缓存还在有效期内则直接使用缓存;如果强缓存不在有效期,协商缓存生效。
-
cache-control
优先级 >expires
优先级 强缓存的expires
和cache-control
同时存在时,cache-control
会覆盖expires
的效果,expires 无论有没有过期
,都无效。 -
ETag
优先级 >Last-Modified
优先级。 协商缓存的Etag
和Last-Modified
同时存在时,Etag
会覆盖Last-Modified
的效果。
第二次请求该资源的时候,如果命中强缓存,则直接从缓存中读取(from disk cache)
,否则协商缓存生效
其实我们第一次获取的资源极有可能是从 CDN 节点的缓存中获取的,也很有可能是从中间代理服务器(nginx,node 等)的缓存中读取的;
6 动态资源
由于动态资源的返回结果不一致,所以这个我们肯定不会在浏览器(中间代理服务器)缓存动态的结果。
不过这里我们可以在后端缓存一些重复率比较高的相关的计算结果.
所以关于动态资源一般前端是不做缓存的。
喜欢这篇文章吗?
加载中...
评论
0 条登录后即可参与评论讨论
加载评论中...
相关文章
目录