cache 强缓存 协商缓存

Caches作用

Web缓存可以保存常见文档副本,当发起Web请求时,如果本地有 “已缓存的" 的副本,就可以直接从本地存储中提取这个文档,而不是去从原始服务器中拿。

减少冗余数据传输

当很多客户端访问原始服务器页面时,服务器会多次传输同一份文档,相同的数据在网络中一遍遍的传输。这些冗余数据会耗尽昂贵的网络带宽,降低传输速度。

使用缓存之后,浏览器只要保留第一条服务器响应的副本,后续对这个资源的访问都可以从缓存副本中得到了,减少了重复流量。

缓解带宽瓶颈

网络为本地网络客户端提供的带宽比服务器提供的带宽大很多。客户端会以路径上最慢的速度访问服务器。如果客户端从本地或者局域网的缓存中得到了一份副本,那么缓存就可以提高性能,尤其在传输大文件时。

降低原始服务器负载

当很多人去访问原始服务器时,会产生巨大流量,从而可能导致服务器崩溃

降低距离时延

将缓存放在本地或者局域网内可以大幅度降低传输距离,加快传输速度。

浏览器缓存过程

Web缓存服务器的基本工作原理很简单,对一条HTTP GET请求的缓存过程如下:

·      接收:缓存从网络中读取抵达的请求报文

·      解析:解析报文,提取首部

·      查询:查询本地是否有副本,如果没有,就发起请求获取副本

·      新鲜度检测:查看本地缓存是否足够新鲜,如果不是,则查询服务器是否有更新

·      创建响应:返回缓存副本

·      发送:将响应发回给客户端

对于浏览器而言,整个过程又可以简化:

·      查询本地副本,如果有且足够新鲜,则直接使用本地副本

·      否则发起请求,验证本地副本是否足够新鲜

以上两个过程分别称为强缓存和协商缓存。

强缓存

强缓存即直接从本地读取缓存副本,不需要发起请求。这种方式是最快的。

强缓存通过HTTP 首部:cache-control管理

cache-control首部

cache-control首部用来指定缓存策略,例如是否能缓存,谁可以缓存,缓存多久

no-cache与no-store

 no-cache:表示必须先与服务器确认返回的响应是否被更改然后才能使用该响应来满足后续对同一个网址的请求。如果资源未被更改,可以避免下载。

no-store禁止浏览器 (和所有中继缓存)存储返回的 任何版本的响应每次用户请求该资源时,都会向服务器发送一个请求,每次都会下载完整的响应

public 与 private

public:即使有关联的 HTTP 认证,甚至响应状态码无法正常缓存,响应也可以被缓存

private:不允许任何中继缓存对其进行缓存 

max-age指令

指定从当前请求开始,允许获取的响应被重用的最长时间(单位为秒)。

通过cache-control的max-age,设置好缓存时间,单位是秒,例如缓存一年:

  1. cache-control: public, max-age=31536000

当使用本地强缓存时,浏览器发回的响应信息是 200 from cache 或者 200 from memory cache,所耗费的时间在几毫秒之间,可以忽略不计。

强缓存的更新问题:如果资源有更新,则希望浏览器使用新的资源。但是在现如今情况下,除了修改资源名称,没有别的办法更新资源。所以现在通常使用的办法是更新资源名称,例如资源名称一般是:

  1. [name]-[hash].ext

在原始文件名之后加入文件哈希值,这样当文件内容修改之后,哈希值就会改变。再修改html文件的引用地址,这样就可以做到资源更新时,自动下载新资源;否则会一直使用本地缓存。

expires首部

expires是HTTP/1.0时期用于强缓存的首部字段它会指定一个绝对的过期日期,如果日期已经过了,说明本地副本不再新鲜了。例如:

  1. Expires: Fri, 09 Dec 2016, 05:00:00 GMT

Expires也是精确到秒的。

由于expires使用的是绝对日期,如果服务器与客户端时间不一致,则会出现缓存不成功或者缓存不更新的问题。所以现在都建议cache-control做强缓存。

协商缓存

本地缓存过期的时候,浏览器就会尝试协商缓存。协商缓存会发起请求,以验证本地副本是否可以使用。也称为再验证的过程。

·      如果验证后显示文档内容变化,浏览器会获取一份新的副本,替代旧副本,缓存在本地

·      如果验证后显示文档内容无变化,浏览器只用获取新的首部和新的过期日期

  1. 根据响应中的状态码来指明文档没有变化。304 Not Modified

验证文档内容是否变化有两种方式,统称为条件GET方法

Last-Modified 与 If-Modified-Since首部

这一对首部通过资源修改日期判断是否有变化,主要过程为:

·      首次获取资源服务器响应中添加首部Last-Modified,说明资源最近一次修改时间。浏览器保存下来这个时间

·      验证资源浏览器带上If-Modified-Since首部值就是Last-Modified返回的时间;服务器比较If-Modified-Since的时间与资源最近一次修改时间:

o   如果最近一次修改时间小于If-Modified-Since的时间,则返回304响应,响应中也会有cache-control、expires、Date首部;

o   如果最近一次修改时间大于If-Modified-Since的时间,则返回新资源,并且更新所对应的全部首部,包括cache-control、expires、Date

ETag与If-None-Match首部

ETag服务器为资源生成的唯一标识字符串只有当文件内容变化时,ETag才会变化。使用过程与Last-Modified类似。

·      首次获取资源:浏览器得到响应首部ETag对应的值

·      验证资源:带上If-None-Match首部,值就是浏览器从服务器获得的ETag值,这样服务器可以比较ETag值来确定客户端缓存是否是最新,如果不是最新,则返回新文档;如果是,直接返回304Not Modified,包括cache-control、expires、Date首部

ETag对比Last-Modified优势

在有些情况下,Last-Modified会出现难以解决的问题:

·      有些文档可能会被周期性的重写,但实际内容并没有变化。而此时Last-Modified会变化,ETag则不会

·      有些文档被修改了,但是修改的内容并不重要,比如注释,不需要更新缓存

·      有些服务器无法准确判断页面最后修改日期

·      有些服务器的文档可能在1秒钟之内就产生变化了,而Last-Modified只能精确到秒,在某些场合下不够精准

如果同时使用ETag和Last-Modified两种验证方式,服务器会优先验证ETag对应的If-None-Match请求首部,如果ETag相同,才会去验证Last-Modified



项目中遇到问题的解释:

如果设置的是no-store,浏览器每次都会请求新的;如果是no-cache,浏览器会优先走304协商缓存;如果这两个都没设置,而是设置了max-age,那在过期时间之内,浏览器不会发送请求到服务器,直接使用本地的。当然如果是cmd+r刷新,是会请求新资源的。

如果不向服务器请求,浏览器就拿不到新资源的。form请求能拿到返回code,但是返回值我们是拿不到的;ajax可以拿到。(所以那个上传文件的组件,form请求失败,需要前端重定向)所以form没有跨域问题,而ajax有跨域问题。而跨域是说请求发送到了服务器,而我们拿不到返回值而已。浏览器觉得跨域拿返回值是危险的。window.open和输入url是一样的。

 

如果后端正确设置了index.html的cache-control规则,是不需要强刷的。后端对index.html设置cache-control: no-cache,no-store,浏览器每次都请求新的html资源,这样用户就会请求新的js和css了(上次是这个规则没设置,所以要强刷)。如果强缓存未过期,在最近一段时间内加载过这个文件,就会from memory,否则就是from disk;from cache也是从缓存里读取。最终都是强缓存,没有请求服务器。304是向服务器做了协商缓存验证,如果没更新才会使用本地资源。

 (上次那个没权限用户总是走缓存的问题,meta头,后端没设置。所以后面自己设置了,并且在登录回调那里把index.html加上时间戳。)


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值