Blog
Blog copied to clipboard
HTTP缓存
HTTP 缓存机制
我们认为浏览器存在一个缓存的数据库,用来存储一些不经常变化的静态文件(img,css,js文件等),一般将缓存分为强制缓存和协商缓存。强制缓存和协商缓存可以同时存在,且强制缓存的优先级大于协商缓存。
强制缓存
如果缓存数据库中已经存在所请求的数据,那么直接从缓存数据库中去获取数据,当缓存数据库中没有所请求的的数据,
强缓存还有两种区分
- from memory cache: 表示从内存中读取的缓存,这种缓存在页面关闭以后缓存就不存了,下次重新打开页面的时候会再次请求
- from disk cache: 表示从硬盘中读取的缓存,这种缓存不会随中页面关闭而失效(cache-control|expires有关),页面再次打开的时候直接从disk中获取
协商缓存
客户端会先去缓存数据库中去获取缓存数据的标识,然后一起发送给服务端,服务端会去验证缓存是否已经失效,如果失效就重新返回新的数据,否则就返回304,客户端直接去缓存数据库中获取数据。
如何判断缓存是否失效
我们可以从服务端返回的 response header 部分的某些字段来判断
- Cache-Control
- Expires
- Last-Modified
- Etag
强制缓存主要用到的是 Expires、Cache-Contro
Expires
它的值是服务器返回的数据有效到期时间,当再次请求时的时间在这个时间以内,那么直接使用缓存。但是服务器时间和客户端时间是有误差的,而且 `Expires` 是http1.0的产物,所以一般使用Cache-Control代替。
Cache-Control 有很多的属性
- private: 客户端可以缓存
- public: 客户端和服务端都可以缓存
- max-age: 缓存将在给的多少秒以后失效
- no-cache: 使用协商缓存
- no-store: 不缓存
协商缓存主要用到的是 ETag,Last-Modifide (将其值作为缓存数据的标识的值,发送给服务器去验证)
Last-Modified: 资源最后一次修改的时间
如果一个资源被修改了,但是他的内容却没有发生变化 Last-Modified也会发生改变
- if-modified-since 作为缓存数据的标识,发送给服务器进行验证
- 当浏览器再次请求的时候会将if-modified-since字段放在请求头里面,服务端接收到请求以后会去比较if-modified-since 和所请求的资源的最后一次修改时间对比,如果一致返回304,否则就返回新的资源。
Etag 服务器返回的,表示当前资源在服务器生成的唯一标识
ETag的计算是通过计算方法得出来的,算法会占用一定的资源,每一次资源发生变化以后就会重新生成ETag。所以一般很少使用ETag
- if-none-match 作为缓存数据的标识,发送给服务器进行验证
- 当浏览器再次请求的时候会将if-none-match放在请求头里面,服务端接收到请求以后会去比较if-none-match和当前所请求的资源的ETag标识对比,如果一致的话就返回304,否则就重新返回资源
如何计算ETag
服务器根据文件的一些信息会计算出ETag:
* 文件的索引节 inode
* 最后一次修改时间 mtime 和大小 size
Nginx官方默认的ETag计算方式是为文件最后修改时间16进制-文件长度16进制。例:ETag: “59e72c84-2404”
自定义:
// 这里额stat是通过nodejs的 fs.statSync 或者 fs.stats发放读取到的文件信息
function stattag (stat) {
var mtime = stat.mtime.getTime().toString(16);
var size = stat.size.toString(16);
return '"' + size + '-' + mtime + '"';
}
ETag 和 last-modified 的优先级
* 如果缓存的资源中两者都有的话,就将两者一起发送给服务器;服务器在判断时会会先判断ETag
如果 `if-non-match` 和 `ETag` 不一样那么重新返回资源 `status=200`,否则就返回304;这个时候不会再去判断 `last-modified`。
* 只存在 `last-modified` :如果 `if-modified-since` 和 `last-modified` 不一样,那么就重新返回资源 `status=200` 否则返回304。
Last-Modified,If-Modified-Since 和 ETag、If-None-Match 一般都是同时启用,这是为了处理Last-Modified不可靠的情况。有一种场景需 要注意:
* 分布式系统里多台机器间文件的 `Last-Modified` 必须保持一致,以免负载均衡到不同机器导致比对失败;
* 分布式系统尽量关闭掉ETag(每台机器生成的ETag都会不一样);
使用缓存的优点
* 减少不必要的请求,减轻服务器的压力,提升网站的性能
* 加快客户端网页加载的速度
最后
关于js,css等文件需要更新,但是设置的缓存时间比较长怎么办???
- 改变js,css等文件的请求url,就会重新请求。所以我们一般可以加上各种查询参数,改变url就好了
- 实际开发中,我们在webpack打包的时候给js,css等文件的文件名加上hash值,每次打包hash值都是不一样的,这样就改变了url。