zl程序教程

您现在的位置是:首页 >  Java

当前栏目

强制缓存和协商缓存的区别

2023-02-18 16:29:05 时间

bug收集:专门解决与收集bug的网站

网址:www.bugshouji.com

01

什么是浏览器缓存

浏览器缓存(Brower Caching)是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。

浏览器缓存的优点有:

1. 减少了冗余的数据传输,节省了网费

2. 减少了服务器的负担,大大提升了网站的性能

3. 加快了客户端加载网页的速度

通过复用以前获取的资源,可以显著提高网站和应用程序的性能。Web 缓存减少了等待时间和网络流量,因此减少了显示资源表示形式所需的时间。通过使用 HTTP缓存,变得更加响应性。

浏览器第一次请求时:

浏览器后续在进行请求时:

浏览器缓存分为强缓存(本地缓存)和协商缓存(对比缓存)

02

术语解释

1. 缓存命中:指在缓存中找到请求的数据.

2. 从服务端传给客户端的(即响应头)

1) cache-control: 缓存相关的设置

2) expires:缓存的过期时间,用来指定资源到期的时间,是服务器端的具体时间点。也就是说Expires=max-age+请求时间,需要和last-modified结合使用。但是上面提到,cache-control的优先级更高。

  3)Last-Modified:表示服务端资源最后修改的时间,也就是传给客户端,用于告诉客户端,服务端资源最后修改的时间

  4)Etag:表示字符串唯一标识符,也是传给客户端,用于告诉客户端,表示服务端资源发生修改了的最新标识。因为Last-Modified的一些缺陷,比如只能标识到时间秒等,所以出现了Etag。当然也可以自定义tag。

如图:

2.从客户端传回服务端的(即请求头):

  1)If-Modified-Since:表示询问服务端,从某个时间点起资源是否修改了。这个时间点一般是服务端Last-Modified返回的时间点。

  2)If-None-Match:表示询问服务端,某个tag字符串值是否不匹配,这个tag值一般是服务端Etag返回的最新的字符串标识符。

如图:

总结:

客户端请求服务端时,服务端在响应头添加 {Last-Modified:最新的时间1,Etag:最新的字符串标识符1},客户端保存服务端的Last-Modified的值和Etag的值,下次请求服务器时,在请求头添加{If-Modified-Since:最新的时间1,Etag:最新的字符串标识符1}。

03

强制缓存

强缓存:浏览器在请求某一资源时,会先获取该资源缓存的header信息,判断是否命中强缓存(cache-control和expires信息),若命中直接从缓存中获取资源信息,包括缓存header信息;本次请求根本就不会与服务器进行通信;在chrome控制台的network选项中可以看到该请求返回200的状态码;

为什么有内存缓存和硬盘缓存呢,怎么区分?这涉及到内存交换的知识了

我们都知道,虽然在运行速度上硬盘不如内存,但在容量上内存是无法与硬盘相提并论的。当运行一个程序需要大量数据、占用大量内存时,内存就会被“塞满”,并将那些暂时不用的数据放到硬盘中,而这些数据所占的空间就是虚拟内存。现在我们也明白为什么pagefile.sys的大小会经常变化了。 内存在计算机中的作用很大,电脑中所有运行的程序都需要经过内存来执行,如果执行的程序分配的内存的总量超过了内存大小,就会导致内存消耗殆尽。为了解决这个问题,Windows中运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,当内存占用完时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张。 举个例子来说,压缩程序在压缩时有时候需要读取文件的很大一部分并保存在内存中作反复的搜索。假设内存大小是128MB,而要压缩的文件有 200MB,且压缩软件需要保存在内存中的大小也是 200MB,那么这时操作系统就要权衡压缩程序和系统中的其他程序,把多出来的那一部分数据放进交换文件。 也就是说在超过VM设置的内存大小后将进行内存交换,跟硬盘内存交换。

强缓存参数

Pragma,是HTTP/1.0标准中定义的一个header属性,请求中包含Pragma的效果跟在头信息中定义Cache-Control: no-cache相同,但是HTTP的响应头没有明确定义这个属性,所以它不能拿来完全替代HTTP/1.1中定义的Cache-control头。通常定义Pragma以向后兼容基于HTTP/1.0的客户端。

expires,这是http1.0时的规范;它的值为一个绝对时间的GMT格式的时间字符串,如Mon, 10 Jun 2015 21:31:12 GMT,如果发送请求的时间在expires之前,那么本地缓存始终有效,否则就会发送请求到服务器来获取资源

cache-control:max-age=number,这是http1.1时出现的header信息,主要是利用该字段的max-age值来进行判断,它是一个相对值;资源第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行;cache-control除了该字段外,还有下面几个比较常用的设置值:

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

注意:如果cache-control与expires同时存在的话,cache-control的优先级高于expires

04

协商缓存

如果没有命中强缓存,浏览器会发送请求到服务器,请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),由服务器根据请求中的相关header信息来比对结果是否协商缓存命中;若命中,则服务器返回新的响应header信息(返回304状态码)更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;否则返回最新的资源内容,

协商缓存参数

协商缓存都是由服务器来确定缓存资源是否可用的,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问,这主要涉及到下面两组header字段,这两组搭档都是成对出现的,即第一次请求的响应头带上某个字段(Last-Modified或者Etag),则后续请求则会带上对应的请求字段(If-Modified-Since或者If-None-Match),若响应头没有Last-Modified或者Etag字段,则请求头也不会有对应的字段。

  1. Last-Modified/If-Modified-Since 二者的值都是GMT格式的时间字符串,具体过程:
    • 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上Last-Modified的header,这个header表示这个资源在服务器上的最后修改时间
    • 浏览器再次跟服务器请求这个资源时,在request的header上加上If-Modified-Since的header,这个header的值就是上一次请求时返回的Last-Modified的值
    • 服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,因为既然资源没有变化,那么Last-Modified也就不会改变,这是服务器返回304时的response header
    • 浏览器收到304的响应后,就会从缓存中加载资源
    • 如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified的Header在重新加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值
  2. Etag/If-None-Match 这两个值是由服务器生成的每个资源的唯一标识字符串,只要资源有变化就这个值就会改变;其判断过程与Last-Modified/If-Modified-Since类似,与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化。

05

强制缓存和协商缓存的区别

06

前端如何实现HTTP缓存

静态的html页面想要设置使用缓存需要通过HTTP的META设置expires和cache-control

设置如下网页元信息:

<meta http-equiv="Cache-Control" content="max-age=7200" />
<meta http-equiv="Expires" content="Mon, 20 Jul 2013 23:00:00 GMT" />

语法:

<meta http-equiv="content-type|default-style|refresh" content="值">

以下场景均不能做浏览器缓存: 1. HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告诉浏览器不用缓存的请求

2. 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的

3. 经过HTTPS安全加密的请求,也存在例外情况

4. POST请求无法被缓存

5. HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存


苟有恒 , 何必三更眠五更起