HTTP缓存

HTTP缓存

对于已经请求过的资源,客户端或代理服务器会将其副本保存在本地存储中,并且在下次请求同⼀资源时,⾸先检 查缓存中是否存在有效的副本。如果存在有效的缓存,就直接读取本地的数据,不必在通过⽹络获取服务器的响应 了,这就是 HTTP缓存

HTTP 缓存有两种实现⽅式,分别是强制缓存和协商缓存

强制缓存

强缓存:浏览器判断请求的⽬标资源是否有效命中强缓存,如果命中,则可以直接从内存中读取⽬标资源,⽆需与服务器做任何通讯。

  • Expires强缓存 :设置⼀个强缓存时间,此时间范围内,从内存中读取缓存并返回,因为 Expires 判断强缓存过期的机制是获取本地时间戳,与之前拿到的资源⽂件中的 Expires 字段的时间做⽐较。来判断是否需要对服务器发起请求, 所以这⾥有⼀个巨⼤的漏洞:“如果我本地时间不准咋办?”正是因为这个原因,该字段⽬前已经基本上被废弃了。
  • Cache-Control强缓存 : http1.1 中增加该字段,只要在资源的响应头上写上需要缓存多久就好了,单位是 秒。 Cache-Control:max-age=N , 有max-age、s-maxage、no-cache、no-store、private、public这 六个属性。
  1. max-age 决定客户端资源被缓存多久。
  2. s-maxage 决定代理服务器缓存的时⻓。
  3. no-cache 表示是强制进⾏协商缓存。
  4. no-store 是表示禁⽌任何缓存策略。
  5. public 表示资源既可以被浏览器缓存也可以被代理服务器缓存。
  6. private 表示资源只能被浏览器缓存,默认为private  

具体的流程如下:

  1. 当浏览器第⼀次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间⼤⼩;
  2. 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使⽤该缓存,否则重新请求服务器;
  3. 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。 

协商缓存

当我们在浏览器使⽤开发者⼯具的时候,你可能会看到过某些请求的响应码是 304 ,这个是告诉浏览器可以使⽤ 本地缓存的资源,通常这种通过服务端告知客户端是否可以使⽤缓存的⽅式被称为协商缓存。 

 

1. 基于 Last-Modified 和 If-Modified-Since 的协商缓存 流程:

  • ⾸先需要在服务器端读出⽂件修改时间
  • 将读出来的修改时间赋给响应头的 Last-Modified 字段。
  • 最后设置 Cache-control:no-cache
  • 当客户端读取到 Last-Modified 的时候,会在下次的请求标头中携带⼀个字段: If-Modified-Since ,⽽这 个请求头中的 If-Modified-Since 就是服务器第⼀次修改时候给他的时间
  • 之后每次对该资源的请求,都会带上 If-Modified-Since 这个字段,⽽服务端就需要拿到这个时间并再次读 取该资源的修改时间,让他们两个做⼀个⽐对来决定是读取缓存还是返回新的资源
  • 如果最后修改时间较新( Last-Modified的时间比If-Modified-Since 更接近当下),说明资源⼜被改过,则返回最新资源, HTTP 200 OK
  • 如果最后修改时间较旧 ( Last-Modified的时间比If-Modified-Since 更早),说明资源⽆新修改,响应 HTTP 304 ⾛缓存。 

缺点:

因为是根据⽂件修改时间来判断的,所以,在⽂件内容本身不修改的情况下,依然有可能更新⽂件修改时间 (⽐如修改⽂件名再改回来),这样,就有可能⽂件内容明明没有修改,但是缓存依然失效了。

当⽂件在极短时间内完成修改的时候(⽐如⼏百毫秒)。因为⽂件修改时间记录的最⼩单位是秒,所以,如果 ⽂件在⼏百毫秒内完成修改的话,⽂件修改时间不会改变,这样,即使⽂件内容修改了,依然响应 HTTP 304 ⾛缓存,不会返回新的 ⽂件。

⽽基于 ETag 的协商缓存则解决了上⾯的两个问题,相⽐于 Last-Modified , ETag 的优先级更⾼。

  • 第⼀次请求某资源的时候,服务端读取⽂件并计算出⽂件指纹,将⽂件指纹放在响应头的 Etag 字段中跟资源 ⼀起返回给客户端。
  • 第⼆次请求某资源的时候,客户端⾃动从缓存中读取出上⼀次服务端返回的 ETag 也就是⽂件指纹。并赋给请 求头的 If-None-Match 字段,让上⼀次的⽂件指纹跟随请求⼀起回到服务端。
  • 服务端拿到请求头中的 If-None-Match 字段值(也就是上⼀次的⽂件指纹),并再次读取⽬标资源并⽣成⽂ 件指纹,两个指纹做对⽐。如果两个⽂件指纹完全吻合,说明⽂件没有被改变,则直接返回 304 状态码和⼀ 个空的响应体并return。如果两个⽂件指纹不吻合,则说明⽂件被更改,那么将新的⽂件指纹重新存储到响应 头的ETag中并返回给客户端 

缺点: ETag需要计算⽂件指纹这样意味着,服务端需要更多的计算开销。如果⽂件尺⼨⼤,数量多,并且计算频 繁,那么ETag的计算就会影响服务器的性能。显然,ETag在这样的场景下就不是很适合。

ETag有强验证和弱验证。

强验证

ETag⽣成的哈希码深⼊到每个字节。哪怕⽂件中只有⼀个字节改变 了,也会⽣成不同的哈希值,它可以保证⽂件内容绝对的不变。但是,强验证⾮常消耗计算量。

弱验证

弱验证是提取⽂件的部分属性来⽣成哈希值。因为不必精确到每个字节,所以他的整体速度会⽐强 验证快,但是准确率不⾼。会降低协商缓存的有效性 。

协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段来使⽤,只有在未能命中强制缓存的时候, 才能发起带有协商缓存字段的请求

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值