HTTP缓存策略,强缓存,协商缓存

HTTP缓存策略,强缓存,协商缓存

1:测试文件

服务端 app.js:

let http = require('http');
let fs = require('fs');
let url = require('url');
let path = require('path');

http.createServer(function (req, rep) {

    let pathname = url.parse(req.url).pathname;
    
    let data = fs.readFileSync(path.normalize(__dirname + pathname,'utf-8'));

    rep.end(data);
})
.listen(9090);

这里首先获取请求 url ,然后拼接路径查找该文件,你的文件不一定在此。

你也可以直接 let data = fs.readFileSync(‘./test1.jpg’,'utf-8'));app.js 相对目录查找对应的文件。(这里是使用的是同步读取文件)

然后执行 node app.js 启动我们的服务器。

客户端端 index.html:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <img src="http://localhost:9090/test1.jpg" alt="test">
</body>
</html>

目录看起来像这样:

在这里插入图片描述

2:强缓存

2.1:Expires

你的格式看起来应该像这样的:Expires: Sun, 17 Jul 2022 14:10:48 GMT

http.createServer(function (req, rep) {

    let pathname = url.parse(req.url).pathname;

    let date = new Date();
    
    date.setMinutes(date.getMinutes()+1);

    rep.writeHead(200, { 'Expires' : date.toUTCString() });
    
    let data = fs.readFileSync(path.normalize(__dirname + pathname,'utf-8'));

    rep.end(data);
})

这里我们设置了 1 分钟强缓存,一分钟之内,不需要请求服务器。

在这里插入图片描述
刷新 index.html 查看控制台,可以发现相应头出现了 Expires 字段。

在这里插入图片描述

这时是在缓存中获取数据。

Expires 是有缺点的,它比对的时间是和本机系统时间有关,如果把系统时间调整了,可能会造成缓存失效。对系统和服务器时间要求较高。为了解决这个问题,可以使用 Cache-Control 相对时间缓存 解决。

2.2:Cache-Control

Cache-Control 虽然可以设置 强缓存 ,但通过设置 Cache-Control : no-cache 可以使用 协商缓存

2.2.1:max-age

设置最大相对过期时间,单位为

http.createServer(function (req, rep) {

    let pathname = url.parse(req.url).pathname;

    rep.writeHead(200, { 'Cache-Control' : 'max-age=30' });
    
    let data = fs.readFileSync(path.normalize(__dirname + pathname,'utf-8'));

    rep.end(data);
})

设置 30 秒后过期。

刷新 index.html

在这里插入图片描述

2.2.2:s-maxage

它的用法和 max-age 相同,不过它是设置 代理服务器 的缓存时间。

2.2.3:public

public 用法:Cache-Control : 'public,max-age=3600'

它的作用是 代理服务器可以缓存

2.2.4:private

private 用法:Cache-Control : 'private,max-age=3600'

它的作用是 个人可以缓存,代理服务器不可以缓存

默认是 private

2.2.5:no-cache

private 用法:Cache-Control : 'no-cache'

设置 no-cache 后,在发布缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证 (协商缓存验证)。

2.2.6:no-store

它的作用是 禁止缓存

3:协商缓存

协商缓存 每次都会向 服务端 发送请求,由 服务端 来告诉 客户端 是否使用缓存。

如果使用缓存 服务端 需要返回 304 状态吗。

3.1:Last-Modified/If-Modified-Since

服务端响应:Last-Modified

客户端发送:If-Modified-Since

服务端接收到 If-Modified-Since ,由 服务端 比对两次时间是否相同,如果不同返回数据,如果相同则返回 304 告诉 客户端 使用缓存。

http.createServer(function (req, rep) {

    let pathname = url.parse(req.url).pathname;

    let time = fs.statSync(path.normalize(__dirname + pathname)).mtime.toUTCString()
    let ifMdifiedSince = req.headers['if-modified-since'];

    if(ifMdifiedSince===time){
        rep.statusCode = 304
        rep.end()
        return
    }

    rep.setHeader("Cache-Control",'no-cache');
    rep.setHeader('Last-Modified' ,time);
    let data = fs.readFileSync(path.normalize(__dirname + pathname,'utf-8'));
    rep.end(data);
})
.listen(9090);

在这里插入图片描述

可以发现这里只使用了 113B 内存。

3.1.1:既然是缓存为什么还会占用宽带?

协商缓存并不是不发送请求,而是发送请求后,由 服务端 判断这次结果是否使用缓存,但请求还是到达我们服务器了。如果确认缓存,则 服务端 需要设置 304 状态吗,否则则不设置。

3.1.2:测试是否缓存了

在这里插入图片描述

首先清除缓存:

刷新查看:

在这里插入图片描述
原图片大小 73.8kb ,但缓存后我们只使用了 113B

注意:Last-Modified 最小单位为秒,如果相差时间小于 1 秒,则该功能失效。

3.2:Etag

Etag 是根据文件唯一指纹判断的,每次修改文件文件指纹都会发生改变。

更多相关知识:javascript获取文件sha-256,sha-384,sha-512摘要,验证文件是否被篡改,验证文件一致性,文件安全管理,计算文件的MD5值

服务端返回 Etag 响应头。

客户端自动发送 If-None-Match 头。

由服务端判断是否缓存,如果缓存,服务端需要返回 304 状态吗。

let http = require('http');
let fs = require('fs');
let url = require('url');
let path = require('path');
var crypto = require('crypto');

http.createServer(function (req, rep) {

    let pathname = url.parse(req.url).pathname;
    let data = fs.readFileSync(path.normalize(__dirname + pathname, 'utf-8'));
    const hash = crypto.createHash('md5');
    hash.update(data, 'utf8');
    const md5 = hash.digest('hex');

    let ifNoneMatch = req.headers['if-none-match'];

    if (ifNoneMatch === md5) {
        rep.statusCode = 304
        rep.end()
        return
    }

    rep.setHeader("Cache-Control", 'no-cache');
    rep.setHeader('Etag', md5);
    rep.end(data);
})
.listen(9090);

在这里插入图片描述
我们的内容已经被缓存了,并没有从服务端请求图片。

注意:虽然 Etag 解决了 Last-Modified 最小单位 的问题,但是计算文件指纹信息比较消耗内存,所以 Etag 并不能完全取代 Last-Modified。所以具体使用哪个,需要我们根据使用场景综合考虑。

4:怎么同时兼顾强缓存和协商缓存的优点

现在我们知道 协商缓存 是需要发送请求的,但可以较准确的知道文件的更改时机,更快的更新我们的缓存。

强缓存 虽然不需要发送请求,但无法尽快知道文件的修改变动,可能造成用户长时间获取不到最新的内容。

有没有一种方式,同时实现 不需要发送请求到服务器 但又可以 尽快获取最新的内容 呢?

想实现这种需求,我们首先需要设置成强缓存。

let http = require('http');
let fs = require('fs');
let url = require('url');
let path = require('path');

http.createServer(function (req, rep) {

    let pathname = url.parse(req.url).pathname;
    let data = fs.readFileSync(path.normalize(__dirname + pathname, 'utf-8'));
   
    rep.writeHead(200,{'Cache-Control':'max-age=3600'});
    rep.end(data);
})
.listen(9090);

当我们文件更新时,我们可以添加一个文件后缀。

比如:我们请求的文件是 http://localhost:9090/test1.jpg

我们可以添加一个后缀,改成 http://localhost:9090/test1.jpg?t=123456

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <img src="http://localhost:9090/test1.jpg?t=123456" alt="">
</body>
</html>

这样不仅强缓存了,而且当文件更新时,还能发起请求获取最新的文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一拖再拖 一拖再拖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值