您的位置:

从强缓存和协商缓存两个方面深入探究缓存机制

一、强缓存

强缓存主要是指利用http响应报文头中的Expires和Cache-Control字段来判断缓存是否失效,如果没有失效则使用本地缓存数据。

1. Expires字段

Expires: Wed, 21 Oct 2020 07:28:00 GMT

Expires是一个正好过期的日期时间,表示该时间前的响应都是有效的,即缓存在这个时间之前可以使用。但是该字段存在一些弊端,就是服务器返回的时间是在服务器端设置的,客户端与服务器端的时间可能不一致导致响应失效。

2. Cache-Control字段

Cache-Control: max-age=31536000

Cache-Control是HTTP/1.1协议新增的字段,它的值是max-age=xxxx,表示该响应在xxxx秒内是有效的,无论是否过期,都应该使用本地缓存。

同时,Cache-Control还可以设置其他属性,详情如下:

  • public:响应可以被所有的客户端缓存。
  • private:响应只能被单个用户缓存,不能被共享缓存、代理缓存等复用。
  • no-cache:客户端缓存服务器返回的响应,但在使用这些缓存数据之前,必须先向原服务器请求验证资源是否被修改过。
  • no-store:响应中禁止写入缓存,即不允许缓存此响应的任何版本。

二、协商缓存

协商缓存主要是利用http报文头中的Etag和Last-Modified字段结合缓存验证来决策是否使用缓存数据。如果服务器判断请求的资源未发生改变,则返回304 Not Modified状态码,告诉客户端可以使用本地缓存数据。

1. Etag字段

Etag: "2e22c4-d-560ac04e56b89"

Etag是一个类似于版本号的字段,由服务器返回,客户端根据这个值来判断缓存是否失效,可以认为是一个文件的唯一标识符。当客户端再次请求该文件时,通过If-None-Match字段带上上一次返回的Etag值告诉服务器本地缓存的版本号,服务器根据该值来判断缓存是否失效。

2. Last-Modified字段

Last-Modified: Mon, 19 Oct 2020 08:42:54 GMT

Last-Modified是一个时间戳,表示该文件最后一次修改的时间。当客户端再次请求该文件时,通过If-Modified-Since字段带上上一次返回的Last-Modified值告诉服务器本地缓存的最后修改时间,服务器根据该值来判断缓存是否失效。

3. 缓存验证

如果客户端请求的资源没有过期,则服务器会返回304 Not Modified状态码,告诉客户端可以使用本地缓存数据。此时响应报文中的实体主体不需要携带内容,通过设置头信息如下:

HTTP/1.1 304 Not Modified
Etag: "2e22c4-d-560ac04e56b89"
Cache-Control: max-age=31536000

三、应用场景

1. 强缓存

强缓存适用于静态资源不经常更新的场景,比如js、css、图片等静态文件。使用强缓存可以减少对服务器的请求,提高页面加载速度。

2. 协商缓存

协商缓存适用于动态数据或者静态文件的更新比较频繁的场景,协商缓存能够减少对服务器的请求次数,避免浪费带宽,提升用户体验。

四、代码示例

1. 强缓存

app.use(express.static(path.join(__dirname, 'public'), {
    maxAge: 60 * 60 * 24 * 365, // 单位为秒
    etag: false,
    lastModified: false
}));

设置maxAge参数为一年,表示客户端对于该资源的有效期为1年,当客户端再次访问该资源时会首先从本地缓存中查找,如果本地缓存失效则再向服务端发起请求。

2. 协商缓存

app.get('/api/data', function(req, res) {
    const data = {
        "name": "Tom",
        "age": 20,
        "address": "Beijing"
    };
    const time = new Date();
    res.set('Last-Modified', time.toUTCString());
    res.set('Expires', new Date(Date.now() + 60000).toUTCString());
    res.send(data);
});

设置Last-Modified和Expires响应头,告诉客户端本次响应的最后修改时间和过期时间,在客户端再次请求该资源时通过If-Modified-Since和If-None-Match两个字段进行验证,判断是否使用本地缓存。

五、总结

缓存机制是Web性能优化的重要方面,强缓存和协商缓存两种缓存方式在不同的业务场景下均能提升页面性能,减少请求次数,提高用户体验。在使用缓存机制时,需要根据具体的业务场景选择合适的缓存方式和合理的缓存时间,并进行定期的缓存清理,避免数据一直存储在本地缓存导致出现的一些问题。