浏览器缓存机制

319 阅读13分钟

目录

1、DNS缓存 
2、CDN缓存
3、浏览器缓存

一、DNS缓存

1、什么是DNS

DNS(Domain Name System,域名系统),因特网上作为域名IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。

解析过程: www.dnscache.com (域名) - DNS解析 -> 11.222.33.444 (IP地址)

2、DNS查询过程如下:

1、首先搜索浏览器自身的DNS缓存,如果存在,则域名解析到此完成。

2、如果浏览器自身的缓存里面没有找到对应的条目,那么会尝试读取操作系统的hosts文件看是否存在对应的映射关系,如果存在,则域名解析到此完成。

3、如果本地hosts文件不存在映射关系,则查找本地DNS服务器(ISP服务器,或者自己手动设置的DNS服务器),如果存在,域名到此解析完成。

4、如果本地DNS服务器还没找到的话,它就会向域名服务器发出请求,进行查询。

二、CDN缓存

全称 Content Delivery Network,即内容分发网络。

CDN缓存

关于CDN缓存,在浏览器本地缓存失效后,浏览器会向CDN边缘节点发起请求。类似浏览器缓存,CDN边缘节点也存在着一套缓存机制。CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的 Cache-control: max-age的字段来设置CDN边缘节点数据缓存时间。

当浏览器向CDN节点请求数据时,CDN节点会判断缓存数据是否过期,若缓存数据并没有过期,则直接将缓存数据返回给客户端;否则,CDN节点就会向服务器发出回源请求,从服务器拉取最新数据,更新本地缓存,并将最新数据返回给客户端。 CDN服务商一般会提供基于文件后缀、目录多个维度来指定CDN缓存时间,为用户提供更精细化的缓存管理。

CDN 优势

CDN节点解决了跨运营商和跨地域访问的问题,访问延时大大降低。 大部分请求在CDN边缘节点完成,CDN起到了分流作用,减轻了源服务器的负载。

三、浏览器缓存(http缓存)

1、什么浏览器缓存

当浏览器请求一个网站的时候,会加载各种各样的资源,比如:HTML文档、图片、CSS和JS等文件。对于一些不经常变的内容,浏览器会将他们保存在本地的文件中,下次访问相同网站的时候,直接加载这些资源,加速访问。

这些被浏览器保存的文件就被称为缓存(不是指Cookie或者Localstorage)。

简单来说,浏览器缓存其实就是浏览器保存通过HTTP获取的所有资源,是浏览器将网络资源存储在本地的一种行为

2、缓存资源去哪了

如何知晓浏览器是读取了缓存还是直接请求服务器?如下图网站来做个示例:

第一次打开该网站后,如果再次刷新页面。会发现浏览器加载的众多资源中,有一部分size有具体数值,然而还有一部分请求,比如图片、css和js等文件并没有显示文件大小,而是显示了 from disk cache 或者 from memory cache 字样。这就说明了,该资源直接从本地硬盘或者浏览器内存读取,而并没有请求服务器。

memory cache

MemoryCache顾名思义,就是将资源缓存到内存中,等待下次访问时不需要重新下载资源,而直接从内存中获取。Webkit早已支持memoryCache。目前Webkit资源分成两类,一类是主资源,比如HTML页面,或者下载项,一类是派生资源,比如HTML页面中内嵌的图片或者脚本链接,分别对应代码中两个类:MainResourceLoader和SubresourceLoader。虽然Webkit支持memoryCache,但是也只是针对派生资源,它对应的类为CachedResource,用于保存原始数据(比如CSS,JS等),以及解码过的图片数据。

disk cache

DiskCache顾名思义,就是将资源缓存到磁盘中,等待下次访问时不需要重新下载资源,而直接从磁盘中获取,它的直接操作对象为CurlCacheManager。

-memory cachedisk cache
相同点只能存储一些派生类资源文件只能存储一些派生类资源文件
不同点退出进程时数据会被清除退出进程时数据不会被清除
存储资源一般脚本、字体、图片会存在内存当中一般非脚本会存在内存当中,如css等

3、http报文中与缓存相关的首部字段

  1. 通用首部字段(就是请求报文和响应报文都能用上的字段)

  2. 请求首部字段

  3. 响应首部字段

  4. 实体首部字段

4、浏览器缓存过程

5、浏览器缓存机制

根据上面四种类型的首部字段不同使用策略,浏览器中缓存可分为强缓存协商缓存.

浏览器再向服务器请求资源时,首先判断是否命中强缓存,再判断是否命中协商缓存!

1)浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器

2)当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源;

3)强缓存与协商缓存的共同点是:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;区别是:强缓存不发请求到服务器,协商缓存会发请求到服务器。

4)当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。

5.1 强缓存:Expires&Cache-Control

浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。

这里的 header 中的信息指的是 expires 和 cache-control。它们都用来表示资源在客户端缓存的有效期。

这两个header可以只启用一个,也可以同时启用,当response header中,Expires和Cache-Control同时存在时,Cache-Control优先级高于Expires

一、Expires

该字段是 http1.0 时的规范,它的值为一个绝对时间的 GMT 格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。

二、Cache-Control

Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。

Cache-Control 是 http1.1 时出现的 header 信息,主要是利用该字段的max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。

语法

缓存请求指令:客户端可以在HTTP请求中使用的标准 Cache-Control 指令。

Cache-Control: max-age=[seconds]

Cache-Control: max-stale[='seconds']

Cache-Control: min-fresh=[seconds]

Cache-control: no-cache

Cache-control: no-store

Cache-control: no-transform

Cache-control: only-if-cached

缓存响应指令: 服务器可以在响应中使用的标准 Cache-Control 指令。

Cache-control: must-revalidate

Cache-control: no-cache

Cache-control: no-store

Cache-control: no-transform

Cache-control: public

Cache-control: private

Cache-control: proxy-revalidate

Cache-Control: max-age=[seconds]

Cache-control: s-maxage=[seconds]

指令

可缓存性

public

表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容(例如,该响应没有max-age指令或Expires消息头)。

private

表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容。

no-cache

在发布缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证。

no-store

缓存不应存储有关客户端请求或服务器响应的任何内容。

到期

max-age=[seconds]

设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与Expires相反,时间是相对于请求的时间。

s-maxage=[seconds]

覆盖max-age或者Expires头,但是仅适用于共享缓存(比如各个代理),私有缓存会忽略它。

max-stale[='seconds']

表明客户端愿意接收一个已经过期的资源。可以设置一个可选的秒数,表示响应不能已经过时超过该给定的时间。

min-fresh=[seconds]

表示客户端希望获取一个能在指定的秒数内保持其最新状态的响应。

stale-while-revalidate=[seconds]

表明客户端愿意接受陈旧的响应,同时在后台异步检查新的响应。秒值指示客户愿意接受陈旧响应的时间长度。

stale-if-error=[seconds]

表示如果新的检查失败,则客户愿意接受陈旧的响应。秒数值表示客户在初始到期后愿意接受陈旧响应的时间。

重新验证和重新加载

must-revalidate

一旦资源过期(比如已经超过max-age),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求。

proxy-revalidate

与must-revalidate作用相同,但它仅适用于共享缓存(例如代理),并被私有缓存忽略。

immutable

表示响应正文不会随时间而改变。资源(如果未过期)在服务器上不发生改变,因此客户端不应发送重新验证请求头(例如If-None-Match或If-Modified-Since)来检查更新,即使用户显式地刷新页面。在Firefox中,immutable只能被用在 https:// transactions. 有关更多信息,请参阅这里。

其他

no-transform

不得对资源进行转换或转变。Content-Encoding、Content-Range、Content-Type等HTTP头不能由代理修改。例如,非透明代理或者如Google's Light Mode可能对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量。no-transform指令不允许这样做。

only-if-cached

表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝。

5.2 协商缓存: Last-Modified&Etag

当浏览器对某个资源的请求没有命中强缓存,就会发一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回的http状态为304并且会显示一个Not Modified的字符串

协商缓存是利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】这两对Header来管理的。

Last-modified

服务器端文件的最后修改时间,需要和cache-control共同使用,是检查服务器端资源是否更新的一种方式。

【Last-Modified,If-Modified-Since】的控制缓存的原理,如下:

1、浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Last-Modified的header,这个header表示这个资源在服务器上的最后修改时间:

2、浏览器再次跟服务器请求这个资源时,在request的header上加上If-Modified-Since的header,这个header的值就是上一次请求时返回的Last-Modified的值:

3、服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容,response header中不会再添加Last-Modified的header;如果有变化,就正常返回资源内容这是服务器返回304时的response header:

ETag

使用ETag可以解决Last-modified存在的一些问题:

a、某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新

b、如果资源修改非常频繁,在秒以下的时间内进行修改,而Last-modified只能精确到秒

c、一些资源的最后修改时间改变了,但是内容没改变,使用ETag就认为资源还是没有修改的。

【ETag、If-None-Match】它们的缓存管理的方式是:

1、浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上ETag的header,这个header是服务器根据当前请求的资源生成的一个唯一标识,这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改时间没有关系,所以能很好的补充Last-Modified的问题: 2、浏览器再次跟服务器请求这个资源时,在request的header上加上If-None-Match的header,这个header的值就是上一次请求时返回的ETag的值: 3、服务器再次收到资源请求时,根据浏览器传过来If-None-Match和然后再根据资源生成一个新的ETag,如果这两个值相同就说明资源没有变化,否则就是有变化;如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化:

5.3不同刷新的请求执行过程

浏览器地址栏中写入URL,回车

浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿。(最快)

F5

F5就是告诉浏览器,别偷懒,好歹去服务器看看这个文件是否有过期了。于是浏览器发送一个请求带上If-Modify-since。

Ctrl+F5

告诉浏览器,先把缓存中的这个文件删了,然后再去服务器请求个完整的资源文件下来。于是客户端就完成了强行更新的操作.