mengtuifrontend / Blog

芦叶满汀洲,寒沙带浅流。二十年重过南楼。柳下系船犹未稳,能几日,又中秋。 黄鹤断矶头,故人今在否?旧江山浑是新愁。欲买桂花同载酒,终不似,少年游。
18 stars 5 forks source link

HTTP缓存 #18

Open shenxuxiang opened 5 years ago

shenxuxiang commented 5 years ago

HTTP 缓存机制

我们认为浏览器存在一个缓存的数据库,用来存储一些不经常变化的静态文件(img,css,js文件等),一般将缓存分为强制缓存和协商缓存。强制缓存和协商缓存可以同时存在,且强制缓存的优先级大于协商缓存。

强制缓存

如果缓存数据库中已经存在所请求的数据,那么直接从缓存数据库中去获取数据,当缓存数据库中没有所请求的的数据,

强缓存还有两种区分

协商缓存

客户端会先去缓存数据库中去获取缓存数据的标识,然后一起发送给服务端,服务端会去验证缓存是否已经失效,如果失效就重新返回新的数据,否则就返回304,客户端直接去缓存数据库中获取数据。

如何判断缓存是否失效

我们可以从服务端返回的 response header 部分的某些字段来判断

强制缓存主要用到的是 Expires、Cache-Contro

Expires
它的值是服务器返回的数据有效到期时间,当再次请求时的时间在这个时间以内,那么直接使用缓存。但是服务器时间和客户端时间是有误差的,而且 `Expires` 是http1.0的产物,所以一般使用Cache-Control代替。
Cache-Control 有很多的属性

协商缓存主要用到的是 ETag,Last-Modifide (将其值作为缓存数据的标识的值,发送给服务器去验证)

Last-Modified: 资源最后一次修改的时间

如果一个资源被修改了,但是他的内容却没有发生变化 Last-Modified也会发生改变

Etag 服务器返回的,表示当前资源在服务器生成的唯一标识

ETag的计算是通过计算方法得出来的,算法会占用一定的资源,每一次资源发生变化以后就会重新生成ETag。所以一般很少使用ETag

如何计算ETag

服务器根据文件的一些信息会计算出ETag:

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 + '"';
    }
ETaglast-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-SinceETag、If-None-Match 一般都是同时启用,这是为了处理Last-Modified不可靠的情况。有一种场景需 要注意:
* 分布式系统里多台机器间文件的 `Last-Modified` 必须保持一致,以免负载均衡到不同机器导致比对失败;
* 分布式系统尽量关闭掉ETag(每台机器生成的ETag都会不一样);

使用缓存的优点

* 减少不必要的请求,减轻服务器的压力,提升网站的性能
* 加快客户端网页加载的速度

最后

关于js,css等文件需要更新,但是设置的缓存时间比较长怎么办???