Http缓存策略之强缓存和协商缓存

缓存的目的是,减少客户端和服务器之间数据传输,以此来达到减少服务端压力和优化客户端体验,比如一个Web站点,其中某些依赖的资源可能十年都不会变动,此时对这种资源进行缓存就非常合适。常说的缓存一般有两种,强缓存和协商缓存(弱缓存)

Http1.1协议规范

强缓存 Cache-Control

主要使用的是Cache-control响应头,如Cache-Control:max-age=3600,当某个资源设置了该请求头后,再一个小时内再次缓存该资源(url)时,不会再请求服务器,而是直接从缓存中读取 image.png 上面这张截图是知乎的某个页面加载的javascript脚本,请求头中被设置了cache-control:max-age=31536000,这个秒数换算下来是一年的时间,一年内我再次访问都不会再请求服务器,并且浏览器也在请求的状态码后标记了来自内存缓存(from memory cache)

协商缓存 Etag

当请求资源时,服务器会返回特征值,名为etag响应头,当强缓存的有效期过了后,浏览器会自动携带一个请求头名为If-None-Match,值就是响应头返回的etag的值。相当于会带着标识去访问服务器,这个资源目前该不该更新,具体是返回200还是304,就全看服务器。

  • 返回304,告诉客户端该资源没有变过,继续使用,并且重新开始计算强缓存时间(如果有设置的话)
  • 返回200,告诉客户端资源可以删了,服务器会返回新的资源

搭建一个静态服务器动手验证

为了更方便的理解,这里用nginx作简单的配置方便测试,为8080端口如下配置,其中/Users/mongielee/cache-demo改成自己的站点路径,站点内只需要两个文件,一个index.html,一个main.js

    server {
        listen       8080;
        server_name  localhost;

        location / {
            root   /Users/mongielee/cache-demo;
            index  index.html index.htm;
        }

        location ~ \.js$ {
            root /Users/mongielee/cache-demo;
            add_header Cache-Control max-age=10;	    
        }
    }
复制代码

这里的配置主要是add_header Cache-Control max-age=10,该配置为所有js后缀的资源都添加了10s都缓存时间,文件内容如下

image.png 启动或重启nginx服务后,访问localhost:8080

image.png 可以看到响应头中携带着文件标识etag和强缓存比标记cache-control,此时十秒内再次访问main.js资源,浏览器不会再发请求而是使用内存缓存

image.png10秒过后再访问main.js,浏览器就在请求头带上If-None-Match标记,值为上一次请求的响应头中的etag,带上If-None-Match这一步浏览器会自动处理,此时返回的状态码就是304,说明文件没有被修改,此时重新计算Cache-Control的值

image.png 如果在二次请求前,服务器文件被修改,那么在强缓存过期后,协商缓存会返回200状态码,原因是请求头的etag值与服务器计算的不一致,下面图中,服务端新返回的etagxxx-1e,而请求头带的是xx-1a,说明文件被修改过

image.png

Http1.0协议规范

之所以和1.1有不同的内容,原因是1.0并没有设计好,与Cache-Controletag相对应的是ExpiresLast-Modified

强缓存Expires

使用该响应头返回客户端一个时间值,那么导致的问题就是如果客户端修改了时间,那么缓存直接就失效了,以及需要注意的地方是,当cache-controlexpires同时设置时,会忽略掉expires,使用cache-control。在Expires的指定时间内(客户端时间),都会从缓存中读取

image.png

协商缓存If-Modified-Since

Expires的时间过期后,再次访问资源请求头会带上一个If-Modified-Sice,值就是上一次请求的响应头中Last-Modified的值,服务器会进行文件的最后修改时间与请求头的If-Modified-Since进行对比,如果发现时间一致则返回304,若etaglast-modified同时设置则优先采用etag,也就是1.1的规范优先于1.0

这种方式的缺点是,精准只到秒级,如果一秒内对文件进行了两次(多次)修改,则结果就不会正确。下图中两次的时间比对一致,所以返回了304 image.png

应该优先采用1.1规范中的cache-control和etag

什么文件该设置缓存?

这个问题没有标准答案,完全看项目需求,但站点首页是绝对不能缓存的,否则永远无法加载版本迭代后的新内容,不过一般浏览器会禁止这种沙雕行为

完:)

猜你喜欢

转载自juejin.im/post/7204858683112865848