diveDylan / blog

My blog, detail is in the issues list
2 stars 0 forks source link

HTTP缓存 #31

Open diveDylan opened 4 years ago

diveDylan commented 4 years ago

作为面试高频面试题,一直通过博客去了解这个概念总是似懂非懂。我们知道的缓存有本地缓存浏览器缓存,浏览器缓存其实有两种方式,常用的http1缓存还有service worker策略缓存,本文主要介绍http缓存

缓存

什么是缓存?

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术

什么是http cache

通过复用以前获取的资源,可以显着提高网站和应用程序的性能。Web 缓存减少了等待时间和网络流量,因此减少了显示资源表示形式所需的时间。通过使用 HTTP缓存,变得更加响应性。当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。这样带来的好处有:缓解服务器端压力,提升性能(获取资源的耗时更短了)。对于网站来说,缓存是达到高性能的重要组成部分

http cache通过web cache内置对象对RequestResponse进行缓存,更多关于Cache对象的内容,值得一提的是Cache也可以作为Service Worker生命周期的一部分。

缓存的种类

MDN中将缓存大致分为两大类,私有缓存和共享缓存,你肯定联想到了cache-control的两个策略,这个我们稍后也会聊到这一点。其他缓存类型你也一定不会陌生,CDN缓存、网关缓存、反向代理缓存等。

目标

缓存虽然不是必须的,但是重用缓存对于前端的交互提升还是巨大的。 缓存一般作用于GET请求,对其他请求一般无能为力,在service worker中这条可以忽略

缓存控制

cache-control

cache-controlhttp1.1控制缓存机制的一个重要header头,有以下几种形式: 1、 no-store 不使用缓存机制,客户端每次都会重新请求服务器资源 2、no-cache使用缓存,每次需要跟服务器确认是否需要,具体是否是用缓存根据客户端和服务端协议决定,也是通常所说的协商缓存,往往需要搭配其他header头使用ETagLast-Modified等 3、public 指令表示该响应可以被任何中间人(比如cdn,网关)缓存 4、private则表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中

过期时间

过期时间有两种设置方式,两种方式代表的过期时间计算模式也完全不一致。 max-age代表从上次更新到下次需要更新的最大缓存时间 expires是根据指定http-date判断是否是用缓存

下图是第一次请求后响应设置expires后,第二次请求内容显示from disk即来自cache image

### deno Drash
// max-age
this.response.headers.set('cache-control', 'max-age=31536000')
// expires
this.response.headers.set('expires', new Date(Date.now() + 60000).toUTCString())

// http cache get method
fetch('http://localhost:8080/user/1')
fetch('http://localhost:8080/user/2') not cache

不同get请求将不会缓存,这也是 revving (不频繁更新的文件会使用特定的命名方式:在URL后面(通常是文件名后面)会加上版本号。)来更新资源的实现。改方案也常用于现代打包工具。

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

缓存验证

ETagLastModified客户端将响应中的这两个的值转为请求中If-None-MatchIf-Modified-Since两个值,并传给服务器,没有优先级之分

---> 1、 Req
---> 2、Res Headers{ ETag: 'a', LastModified: 'b'} 
---> 3、Req Headers { `If-None-Match`: 'a', `If-Modified-Since`: b}
---> 4、Server compare race 
              If-None-Match === ETag 
              If-Modified-Since >= LastModified
----> 5、得到一个结果将不输出另一个(ETag match ---》 res 304)

ETag code这段代码在Drash中可能不生效issuse--304 ETag Support

if(this.request.getHeaderParam('if-none-match') == "33a64df551425fcc55e4d42a148795d9f25f89d4"){
      this.response.status_code = 304
    } else {
      this.response.headers.set('ETag', "33a64df551425fcc55e4d42a148795d9f25f89d4")
    }
diveDylan commented 4 years ago

Vary

Vary 是一个HTTP响应头部信息,它决定了对于未来的一个请求头,应该用一个缓存的回复(response)还是向源服务器请求一个新的回复。

image

// 根据userAgent决定是否是用缓存,如pc和手机
Vary: User-Agent
// zip or br 请求zip是用缓存
Vary: zip