你不知道的HTTP缓存

这是我参与11月更文挑战的第1天,活动详情查看:11月更文挑战

作为一名前端开发者,在工作中几乎每天都在和HTTP打交道。但是对它深入了解的人却不多,而在面试过程中几乎也是必问的问题。所以有必要了解清楚。

一、什么是HTTP缓存

HTTP缓存指的是: 当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提取使用,而不从原始服务器中提取这个资源。所有的HTTP缓存都是从第二次请求开始的

二、HTTP缓存的分类

http分类,如模型所示: 浏览器缓存机制.png

强缓存

Expires : 设置的缓存过期时间,如果在规定时间内再次发送请求,就会直接使用缓存内容。

Cache-Control :进行缓存控制,具体用途如下所示:

1.可缓存性

public:http通讯的过程中,包括请求的发起方(浏览器),代理缓存服务器都可以进行缓存。
private:只允许请求的发起方(浏览器)进行缓存。
no-cache:可以在请求的发起方(浏览器进行缓存),但是每一次都会去服务器验证资源。
no-store:任何地方都不可以缓存。
复制代码

2.到期设置

max-age:<seconds> 表示缓存多少秒之后会过期,如果只设置max-age没有设置no-cache,浏览器在要请求相同的静态文件时,会看是否在max-age时间内,如果在的会就直接使用缓存中的值了,单独只设置max-age很可能会造成资源得不到及时的更新。会有一定的弊端。
s-maxage:<seconds> 表示代理服务器中的缓存资源多少秒过期,如果同时设置max-age和s-maxage,在浏览器会判断max-age属性,在代理服务器端会判断s-maxage属性。
复制代码

3.重新验证

must-revalidate:缓存过期后都必须去重新验证。(浏览器和代理服务器)
proxy-revalidate:设置此属性代理服务器缓存过期才会去重新验证。
复制代码

协商缓存

Last-Modified : 会记录服务器上次资源修改的最后时间。由于协商缓存都是成对存在的,所以还有一个它的好兄弟要介绍,就是Last-Modified-Since。(记录修改的时间最小单位是 ,这里是有一些问题存在我们在下面详细介绍)

Last-Modified-Since : 这里设置的值就是Last-Modified中的值,进行保存起来,当再次发送请求时,会在请求的头部信息中带着该属性,用于和资源最后修改的时间进行相比对判断是否命中缓存。

Etag : 数字签名,主要就是记录请求的资源内容有没有发生变化,服务器会发生给浏览器的属性值。主要是配合If-Match或者If-None-Match使用。(数字签名生成原理,感兴趣的同学可以了解一下)

If-Match/If-None-Match : 用于记录Etag的值。第一次请求资源时,在server中设置头部信息Etag,值为hash值,当浏览器再次对相同的资源发起请求时,浏览器会设置request的头部,设置If-Match或者If-None-Match的值为之前接收到的Etag的值,这样,server每次取得头部信息If-Match或者If-None-match,与重新计算的hash值进行对比,如果相同,就返回304Not Modified,client使用缓存,如果不相同,就返回更新后的资源。

协商缓存的优缺点

Last-Modified(优点)

1.没有版本问题,每一次的请求都会去服务器进行校验最后的修改时间,如果相同返回304使用缓存资源,否则200调用服务器资源。

Last-Modified(缺点)

上面我们提到记录资源修改时间的最小单位是,会出现一些问题。我们看一下具体问题。

1.只要资源修改,无论内容是否有变化,都会当做一次新的资源给浏览器。

2.由于最小单位是秒,会出现无法在一秒内识别多次修改资源的情况。

3.有一些服务器无法记录准确的最后修改日期,所以就达不到有缓存的效果。

Etag(优点)

1.可以更加 精确的判断资源内容是否被修改。

2.可以识别一秒多次修改的情况。

3.也是不存在版本问题,每次都会和服务器去进行校验。

Etag(缺点)

1.计算Etag会有一定的性能消耗

2.分布式服务器依赖算法:分布式服务器存储的情况下,计算 Etag 的算法如果不一样,会导致浏览器从一台服务器上获得页面内容后到另外一台服务器上进行验证时现 Etag 不匹配的情况。

缓存优先级

1.强缓存与协商缓存的优先级 : 强缓存和协商缓存同时存在,如果强缓存还在生效期则强制缓存覆盖协商缓存,协商缓存不生效;如果强缓存不在有效期,协商缓存生效。即:强缓存 > 协商缓存

2.强缓存的优先级 : 强缓存expires和cache-control同时存在时,则cache-control会覆盖expires,expires无论有没有过期,都无效。即:Cache-Control > Expires

3.协商缓存的优先级 : 协商缓存Etag和Last-Modified同时存在时,则Etag会覆盖Last-Modified,Last-Modified不会生效。即:ETag > Last-Modified。

三、浏览器的缓存过程

1.浏览器第一次加载资源,服务器返回200,浏览器将资源从服务器上请求下载下来,并把response header及该请求的返回时间一并缓存;

2.下一次加载资源时,先比较当前时间和上一次返回200时的时间差,如果没有超过cache-control设置的max-age,则没有过期,命中强缓存,不发请求直接从本地缓存读取该文件(如果浏览器不支持HTTP1.1,则用expires判断是否过期);如果时间过期,则向服务器发送header带有If-None-Match和If-Modified-Since的请求;

3.服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;

4.如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200;

以上大概就是浏览器缓存的全过程,下面配一幅低配版图画仅供参考:

http请求图解.png

四、刷新对缓存的影响

1.点击刷新按钮或者按F5

浏览器直接对本地的缓存文件过期,但是会带上If-Modifed-Since,If-None-Match,这就意味着服务器会对文件检查新鲜度,返回结果可能是304,也有可能是200。

2.用户按Ctrl+F5(强制刷新)

浏览器不仅会对本地文件过期,而且不会带上 If-Modifed-Since,If-None-Match,就相当于第一次去服务器请求资源,返回结果是200。

3.栏回车

浏览器发起请求,按照正常流程,本地检查是否过期,然后服务器检查新鲜度,最后返回内容。

总结

Http 缓存设置起来并不复杂,但却容易被轻视。希望这篇文章可以帮助你们了解Http缓存,文中有写的不妥的地方欢迎指正,也希望看完文章的你可以点一个赞。

Guess you like

Origin juejin.im/post/7032290641929306125