浏览器缓存策略

浏览器缓存主要分为强缓存(本地缓存)和协商缓存(弱缓存)

what

浏览器缓存(Brower Caching)是浏览器对之前请求过的文件进行缓存,以便下一次访问时重复使用,节省带宽,提高访问速度,降低服务器压力

http缓存机制主要在http响应头中设定,响应头中相关字段为Expires、Cache-Control、Last-Modified、Etag。

HTTP 1.0协议中的。简而言之,就是告诉浏览器在约定的这个时间前,可以直接从缓存中获取资源(representations),而无需跑到服务器去获取。


Expires因为是对时间设定的,且时间是Greenwich Mean Time (GMT),而不是本地时间,所以对时间要求较高。

过程

第一次请求网页

浏览器缓存策略_第1张图片

第二次请求相同的网页

浏览器缓存策略_第2张图片

如上图,在浏览器第一次发送请求后,需要再次发送请求时,浏览器会首先获取该资源缓存的header信息,然后根据Cache-Control和expires来判断是否过期。若没过期则直接从缓存中获取资源信息,包括缓存的header的信息,所以此次请求不会与服务器进行通信。如果缓存过期,浏览器会向服务器发送请求,本次请求会带着第一次请求返回的有关缓存的header字段信息,比如以下两种情况:

Etag

客户端会通过If-None-Match头将先前服务器端返回的Etag发送给服务器,服务器会对比这个客户端发过来的Etag是否与服务器的相同,若相同,就将If-None-Match的值设为false,返回状态304,客户端继续使用本地缓存,不解析服务器端发回来的数据。若不相同就将If-None-Match的值设为true,返回状态为200,客户端重新机械服务器端返回的数据;

If-Modified-Since

客户端还会通过If-Modified-Since头将先前服务器端发过来的最后修改时间戳发送给服务器,服务器端通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回最新的内容,如果是最新的,则返回304,客户端继续使用本地缓存。

强缓存

浏览器不会像服务器发送任何请求,直接从本地缓存中读取文件并返回Status Code: 200 OK

浏览器缓存策略_第3张图片

200 form memory cache

不访问服务器,一般已经加载过该资源且缓存在了内存当中,直接从内存中读取缓存。浏览器关闭后,数据将不存在(资源被释放掉了),再次打开相同的页面时,不会出现from memory cache。

200 from disk cache

不访问服务器,已经在之前的某个时间加载过该资源,直接从硬盘中读取缓存,关闭浏览器后,数据依然存在,此资源不会随着该页面的关闭而释放掉下次打开仍然会是from disk cache。

优先访问memory cache,其次是disk cache,最后是请求网络资源

参数

强缓存是利用http头中的ExpiresCache-Control两个字段来控制的,用来表示资源的缓存时间

Expires

是http1.0的规范,它的值是一个绝对时间的GMT格式的时间字符串。比如网页的Expires值是:

expires:Mar, 06 Apr 2020 10:47:02 GMT

这个时间代表这这个资源的失效时间,只要发送请求时间是在Expires之前,那么本地缓存始终有效,则在缓存中读取数据。所以这种方式有一个明显的缺点,由于失效的时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱

Cache-Control

是http1.1中出现的,一般利用该字段的max-age来判断,这个值是一个相对时间。例如:

Cache-Control:max-age=3600 // 代表着资源的有效期是3600秒

除了该字段还有其他的几个常用的值。

  • no-cache不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
  • no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
  • public可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
  • private只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。

Cache-Control与Expires的优先级


Cache-ControlExpires可以在服务端配置同时启用,同时启用的时候Cache-Control优先级高。比如:

cache-control:max-age=691200 
expires:Fri, 06 Mar 2020 10:47:02 GMT

那么表示资源可以被缓存的最长时间为691200秒,会优先考虑max-age

协商缓存

向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源;

参数

协商缓存是由服务器确定缓存资源是否可用。主要涉及到两组header字段:

  • Etag和If-None-Match
  • Last-Modified和If-Modified-Since

Last-Modifed/If-Modified-Since和Etag/If-None-Match是分别成对出现的,呈一一对应关系

Last-Modify/If-Modify-Since

浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间,例如

Last-Modify: Thu,31 Dec 2037 23:59:59 GMT

当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。

Etag/If-None-Match

浏览器缓存策略_第4张图片

从上面看可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag呢?

首先,Etag/If-None-Match 是“实体标签”(Entity Tag)的缩写,是资源的一个唯一标识,资源变化都会导致ETag变化。服务器根据浏览器上送的If-None-Match值来判断是否命中缓存。

因此,Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  • 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
  • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
  • 某些服务器不能精确的得到文件的最后修改时间。

Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。

为什么会出现这两者

区别

强制缓存是根据过期时间来使用的,协商缓存是根据文件有没有修改来使用的,如果过期了就需要使用协商缓存来确定文件有没有修改,如果修改了就需要服务器返回修改后的资源,如果没有修改就还是可以使用缓存的资源。

缺点

强缓存有缺点:比如说,设置了expires,GMT格式,但是浏览器的时间可以改变,因此就通过cache-control返回一个相对时间来。但是假如说资源并没有更新,但是强缓存时间过期了,那就需要重新拉去资源,因此就有了last-modified,但是last-modified的时间单位是s,当1s内有资源修改,那浏览器返回的最后修改时间和上次的修改时间相同,那就不会重新拉取资源,因此推出了etag,通过比对资源内容来判断是否修改

你可能感兴趣的:(浏览器,缓存,服务器,chrome)