1 与缓存相关的字段
Expires:缓存的绝对过期时间
Cache-Control:缓存的相对过期时间
Last-Modified:缓存上一次修改的时间(服务端保存)
If-Modified-Since:缓存上一次修改的时间(客户端保存)
Etag:文件上一次修改生成的版本号(服务端保存)
If-None-Match:文件上一次修改生成的版本号(服务端保存)
6个字段,分别一一对应,Expires与Cache-Control,Last-Modified与If-Modified-Since,Etag与If-None-Match。
2 缓存渐进式了解
上面所讲到的6个字段其实都是渐进式改进的,也即是业务不断升级的过程,下面逐一了解。
2.1 缓存的好处
网站的渲染,其实大部分都是静态资源,例如html、js、css、image等。例如image这些,其实大小有时候还挺大的,如果没有缓存,那么客户端请求渲染页面时候,每次都要去服务端下载该重复文件。
缺点:
浪费用户流量
消耗大量时间下载文件,用户体验感不佳
2.2 Expires
加入缓存,也即是客户端将从服务端请求到的文件缓存到本地,下一次再次请求此文件时,就直接去缓存拿就可以了,不必浪费大量的用户流量和等待时间去请求重复的文件。
然而,这不是完美的,因为服务端有时候会修改该文件哦。如果客户端长期使用缓存中的文件,那么就无法感知服务端的最新文件,那就变成离线状态了,那是不行的。所以服务端给客户端返回了一个Expires字段,该字段是一个绝对时间,表示在该时间段内,可以使用缓存,过期了你再来访问。
图1 Expires字段
如图1所示,该expires是一个服务端的响应字段,同时他是一个GMT的绝对时间,这就有问题了,客户端这边肯定是拿到这个时间,然后将该时间与本地时间相比,在该时间内使用缓存,不在该事件内重新请求文件。那么本地时间他是一个可自我调整的,如果用户自行修改该字段,是不是会造成时间误差问题,造成不必要的误差。
2.3 Cache-Control
针对Expires是一个绝对时间的问题,引入了Cache-Control字段,该字段是一个相对时间问题。格式max-age=31536000,表示在这个时间段内,你就使用缓存就可以了,不用再次请求服务端获取文件。这就完美解决了绝对时间问题所带来的错误。
图2 cache-control
2.4 Last-Modified和If-Modified-Since
当你以为上面已经做到很完美的时候,又有一个新的问题。缓存时间设置不够准确,导致缓存过期,大量重复请求服务端,然而文件其实没修改,那么又要经过多次下载,仿佛有点提升,但是又回到了没有缓存的问题。针对该问题,加入了Last-Modified,该字段表示上一次文件修改的时间,可以把该时间返回给客户端,客户端将该值保存至If-Modified-Since字段,然后下一次缓存过期的时候,将If-Modified-Since字段带上,然后与服务端的Last-Modified比对,如果相同,则证明文件没有被修改过,客户端可继续使用缓存文件,无需重复下载;如果不相同,说明该文件已经修改过,则重新传输到缓存。
读到这里,你一定觉得太完美了。然而,事与愿违,Last-Modified只能精确到秒,现在的带宽速度,1秒内可以修改n+1个文件,所以在你得到该字段的时候,那一瞬间估计文件就已经被修改了,以至于你在后面匹配Last-Modified和If-Modified-Since字段时,以为相等就是没修改,但是其实你一直使用是旧版本的文件。
图3 Last-Modified
2.5 Etag和If-None-Match
争对Last-Modified只能精确到秒的问题,服务端加入了Etag字段,可以理解成版本号(或者唯一ID,就跟mysql插入输入那个唯一id一样)。文件每一次修改就生成新的Etag值,客户端请求时将Etag字段保存到本地的If-None-Match字段。下一次缓存失效的时候,带上If-None-Match字段与服务端的Etag进行比较,如果相同,则证明文件没有被修改过,使用缓存即可;如果不同,则证明文件已经被修改过,服务端重新传输磁盘的新文件给客户端,同时替换缓存的旧文件。
图4 Etag
3 强缓存和协商缓存
下面聊一下常问的一个问题,强缓存和协商缓存,协商缓存有时候也叫对比缓存。
其实顾名思义,强缓存表示的就是,在某时间内,你就给我使用缓存就可以了,不用来请求我服务端。那么使用Expires和Cache-Control字段的,就是使用强缓存的意思咯。
协商缓存(对比缓存):客户端拿着某个字段去与服务端某个字段比较,逻辑判断。相信认真读了上文,就知道使用Last-Modified与If-Modified-Since、Etag与If-None-Match的就是协商缓存。
本文则是HTTP缓存的所有内容,欢迎共鸣。