你可以介绍一下HTTP 的缓存机制吗?
好的,面试官
首先,我大概介绍一下 HTTP 缓存的背景吧,
HTTP 发展到 1.1 版本,在请求传输过程中也存在携带了很多冗余且重复的数据, 比如相同的首部,比如请求头多个固定字段没压缩等等,导致请求性能的下降; 所以这时候提高 HTTP1.1 性能的一种方法就是减少请求,所以缓存机制也就提了上来了。
HTTP 的缓存机制
HTTP 的缓存机制分为两种:一种是强制缓存、一种是协商缓存,强制缓存不成功才走协商缓存。
强制缓存
强制缓存是浏览器的主动行为,在发请求之前它会先看看是否有缓存,缓存是否过期;如果没过期,则直接使用缓存;
这时候,返回的 code 是 200 ,但是会有 from disk cache 的标识,标志着该请求走的是强制缓存。
强制缓存的实现主要依靠 Respond Head 中的两个字段: Cache-Control:相对时间 或 Expires:绝对时间 一般来说, Cache-Control 可以设置得更精细些,所以推荐使用 Cache-Control 来实现强制缓存; 如果上述两个字段同时存在的话, Cache-Control 的优先级更高。
综上,强制缓存就是和拿请求的时间和 Cache-Control (或者 Expires)中的时间作比较, 只要没过期,则浏览器直接返回缓存的数据。
协商缓存
协商缓存是指服务器告诉浏览器是否使用本地缓存,其实本质上就是交由服务器来判断本地缓存是否过期; 若没过期,则直接返回 304 ,告诉浏览器使用本地缓存。 走到了协商缓存,说明强制缓存已经失效,HTTP 请求已经发出
协商缓存的实现也有两种:
-
请求头部中的
If-Modified-Since字段与响应头部中的Last-Modified字段实现Last-Modified记录着资源的最后修改时间,If-Modified-Since表示从某个时间段开始到现在资源未发生改变 在请求的时候,发现有Last-Modified字段,则会将该时间填进If-Modified-Since向服务器发出请求; 服务器根据浏览器发来的时间和目标资源的Last-Modified比较,如果Last-Modified的时间比较小, 说明资源未发生改变,直接响应 304,让浏览器使用本地缓存; 否则返回最新的资源数据,响应 200. -
请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段 响应头部中
Etag:唯一标识响应资源;(思想上有点像 Hash, MD5) 在请求的时候,发现有Etag字段,则会将该值填进If-None-Match向服务器发出请求; 服务器根据浏览器发来的值和目标资源的Etag比较,如果两个值相等, 说明资源未发生改变,直接响应 304,让浏览器使用本地缓存; 否则返回最新的资源数据,响应 200.
综上,强制缓存是由浏览器自己决定资源是否过期,协商缓存是交由服务端来判断; 无论是 最后的修改时间 还是 资源的唯一标识 ,目的就是用于判断资源是否过期; 相对来说 资源的唯一标识 这种实现方式更为可靠, 最后的修改时间 的实现方式存在时间篡改等不可靠性