Http 协议基础知识 2:缓存
缓存
首先缓存有很多种,这里大致介绍下和前端有关的缓存,着重说下 http 协议相关的缓存。
- client 在发起一个 http 请求前,可能先会检查下是否已经请求过这个 uri,如果是并且缓存有效的话,就不用发请求了,直接读取本地缓存即可。这一步的缓存是http协议层面的缓存。
- 当已经请求过的uri在此被较为强制的理由请求时(如用户主动刷新页面),那么client就不能完全使用本地缓存了,它会发起一个带有缓存协商的http请求,和server商量好本地缓存可用的话,server 会返回 304,并且无响应体,client加载本地缓存,否则server返回200,并返回响应体。
- 请求在到达 server 前(这里的server指的是部署代码的server),可能会先到达cdn,cdn的原理是遍布各地的cdn节点在一次接到一个uri请求时,向中控机发起请求,获得该请求的文件,返回给用户并缓存下来。下次同样的请求就直接返回给用户了。这里的 cdn 缓存,不同的cdn实现不一样,有些是缓存文件名,有些是缓存url。所以前端开发人员在使用cdn的时候就需要了解其中是如何进行缓存的,你再中控机上更新一个文件,cdn 节点是否会重新获得该文件。操作不当就会导致更新的内容在用户那里无法生效,因为cdn一直使用的旧的缓存文件。
- 请求穿过历尽万难到达你部署代码的 server 之后,在 server 端还会进行若干缓存,这里就不过多探讨了。与前端关系不大,是后端人员需要关注的。
机制
接下来详细解释下 http 的缓存机制。
http 主要是通过时间和内容两种办法来处理缓存的。
首先,client 发起一个 http 请求之后,server 会在 http 响应头里面告诉 client,这个请求能否被缓存。这里有两个响应头可以用来做这件事儿。
Expires
一个是 Expires
,表示请求的过期时间,是个绝对的时间,如Thu, 04 Jul 2013 06:25:39 GMT
,client就知道,该请求在Expires的时间之前都是可用的,超过这个时间就不可用了。若强制请求不缓存,就设置个已经过去的时间即可。用Expires的缺点就是,这是个绝对的时间,而所有的server和client在绝对时间上,都是有一定误差的。
Cache-Control
另一个是Cache-Control
,常用的就是max-age,表示缓存的有效时间,单位为毫秒。如:Cache-Control:max-age=14400
。在请求该uri之后的max-age之内,认为改请求的缓存是有效的。若强制请求不缓存,可以设置为0。
理论上,Expires
和Cache-Control
只用其一即可,两个都用是非法的。这样便解释了上面提到的第1中缓存的情况。即强缓存,在浏览器中,一般除非用户刷新等主动强制更新缓存的操作,都会采用上面的方法处理缓存。
client已经缓存了某个uri之后,还是需要访问服务器的时候,client和server就要进行缓存协商了。常用的缓存协商有两种方法,一种是最后修改日期,另一种是版本号。
Last-Modified
先说下最后修改日期。请求的响应头中,server可能会写入 Last-Modified 字段,表示改请求最后一次修改的时间。client第二次发送这个请求时,就会带上If-Modified-Since的请求头,告诉server,只有请求内容在某个时段之后修改过,才返回给我。server中看到这个请求头,会验证在某个时段后是否修改过。若修改过,返回200,并返回最新的请求体,否则返回304,告诉client,请使用你的本地缓存吧。
ETag
最后修改日期验证,应该很容易理解,下面说下版本验证,也就是 ETag。
首先,client是不会理解ETag是怎么生成的,它只负责记录 ETag,并告诉 server。至于 server 中如何计算 ETag,也没有规定。只要你遵守一个原则即可:内容不变,ETag 不变,内容变化,ETag 变化。到底你用md5还是什么算法,那就看具体情况了。
请求的响应头中,server会将计算好的ETag返回给client。client下次请求时,会带上 If-None-Match 的请求头,告诉 server,只有 ETag 不匹配的时候,你才返回给我内容,否则我就使用缓存。server端的处理同 Last-Modified 时。
如果同时存在 ETag 和 Last-Modify 验证怎么办呢?server 会同时验证两个,都满足时才返回 304,有一个不满足就要返回 200,给 client 最新的内容。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论