实际操作理解 HTTP 缓存

2024-08-23 01:32

本文主要是介绍实际操作理解 HTTP 缓存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实际操作理解 HTTP 缓存

网上很多优秀的文章介绍了 HTTP 缓存,但大多是文字内容。

最好结合实际操作,方便更好的理解。

实际操作就需要开启一个 HTTP 服务测试 HTTP 协议,建议使用原生的 Node.js 的 http 模块。

不建议使用 Express Koa Egg 等开发框架,因为它们内置了很多功能,不利于学习原生的 API。

开启 HTTP 服务

创建 app.js

// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {res.end('Hello World!')
})server.listen(3000, () => {console.log('running http://localhost:3000')
})

运行:

# 建议使用 nodemon 运行
# npm i -g nodemon
nodemon ./app.js

访问:http://localhost:3000

输出 HTML 内容

// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {res.end(`
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Document</title></head><body><h1>HTTP 缓存</h1></body>
</html>
`)
})server.listen(3000, () => {console.log('running http://localhost:3000')
})

输出 html 文件内容

创建 index.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Document</title></head><body><h1>HTTP 缓存</h1><p>index.html</p></body>
</html>

修改 app.js

// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')
const fs = require('fs')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {// 每次请求今来都要重新读取该文件const data = fs.readFileSync('./index.html')res.end(data)
})server.listen(3000, () => {console.log('running http://localhost:3000')
})

现在每次请求进来,都要读取磁盘文件 index.html

磁盘读取速度,网络速度都会影响响应的速度。

划分请求路径

此时所有路径的请求都返回同样的 html 内容。

这解释了,请求路径只是一个标识,需要返回什么内容,是服务器处理的。

创建 main.js

console.log('this is main.js')

添加 main.js 引入

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Document</title></head><body><h1>HTTP 缓存</h1><p>index.html</p><script src="./main.js"></script></body>
</html>

修改 app.js

// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')
const fs = require('fs')
const url = require('url')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {// 如果请求 /,则返回 index.html// 如果请求 /main.js,则返回 main.jsconst { pathname: path } = url.parse(req.url)if (path === '/') {const data = fs.readFileSync('./index.html')res.end(data)} else if (path === '/main.js') {const data = fs.readFileSync('./main.js')res.end(data)} else {// 不再受理范围之内的,统一返回 404res.statusCode = 404res.end()}
})server.listen(3000, () => {console.log('running http://localhost:3000')
})

缓存针对的是 GET 请求

缓存一般针对的是静态资源,html css js img 等。

缓存针对的是 GET 请求。

缓存操作目标 - MDN

虽然 HTTP 缓存不是必须的,但重用缓存的资源通常是必要的。然而常见的 HTTP 缓存只能存储 GET 响应,对于其他类型的响应则无能为力。

打印请求日志

查看服务器是否接受了请求,可以确认资源是否使用了缓存。

为请求添加日志打印:

// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')
const fs = require('fs')
const url = require('url')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {// 打印请求日志console.log(`${req.method} ${req.url}`)// 如果请求 /,则返回 index.html// 如果请求 /main.js,则返回 main.jsconst { pathname: path } = url.parse(req.url)if (path === '/') {const data = fs.readFileSync('./index.html')res.end(data)} else if (path === '/main.js') {const data = fs.readFileSync('./main.js')res.end(data)} else {// 不再受理范围之内的,统一返回 404res.statusCode = 404res.end()}
})server.listen(3000, () => {console.log('running http://localhost:3000')
})

再次访问页面,观察控制台,可以看到每次请求都打印了日志。

设置缓存

缓存控制 - MDN

通过定义响应头的 Cache-Control 来设置缓存。

http 模块有两个设置响应头的方法:

// 一次设置一个字段
request.setHeader(name, value)
// 一次可以设置多个字段
request.writeHead(statusCode, {name: value,name: value
})
server.on('request', (req, res) => {// 打印请求日志console.log(`${req.method} ${req.url}`)// 如果请求 /,则返回 index.html// 如果请求 /main.js,则返回 main.jsconst { pathname: path } = url.parse(req.url)if (path === '/') {const data = fs.readFileSync('./index.html')res.end(data)} else if (path === '/main.js') {const data = fs.readFileSync('./main.js')// 设置不缓存res.setHeader('Cache-Control', 'no-store')res.end(data)} else {// 不再受理范围之内的,统一返回 404res.statusCode = 404res.end()}
})

查看浏览器的请求日志,可以看到设置的请求头信息。

设置缓存过期时间

过期机制中,最重要的指令是 “max-age=<seconds>”,表示资源能够被缓存(保持新鲜)的最大时间。相对Expires而言,max-age是距离请求发起的时间的秒数。针对应用中那些不会改变的文件,通常可以手动设置一定的时长以保证缓存有效,例如图片、css、js等静态资源。

server.on('request', (req, res) => {// 打印请求日志console.log(`${req.method} ${req.url}`)// 如果请求 /,则返回 index.html// 如果请求 /main.js,则返回 main.jsconst { pathname: path } = url.parse(req.url)if (path === '/') {const data = fs.readFileSync('./index.html')res.end(data)} else if (path === '/main.js') {const data = fs.readFileSync('./main.js')// 缓存20秒res.setHeader('Cache-Control', 'max-age=20')res.end(data)} else {// 不再受理范围之内的,统一返回 404res.statusCode = 404res.end()}
})

再次访问页面,注意要关闭浏览器的 禁用缓存 (Disable cache)。

查看控制台,发现 main.js 的请求日志没有打印,表示浏览器使用了缓存。

浏览器请求日志中也会显示 (memory cache)表示缓存在内存中,假如内容很大,也可能会缓存在磁盘中。

关于 HTTP 缓存可以参考:

一文读懂http缓存(超详细)

HTTP 缓存 - MDN

这篇关于实际操作理解 HTTP 缓存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1097964

相关文章

MySQL 缓存机制与架构解析(最新推荐)

《MySQL缓存机制与架构解析(最新推荐)》本文详细介绍了MySQL的缓存机制和整体架构,包括一级缓存(InnoDBBufferPool)和二级缓存(QueryCache),文章还探讨了SQL... 目录一、mysql缓存机制概述二、MySQL整体架构三、SQL查询执行全流程四、MySQL 8.0为何移除查

深入理解Apache Airflow 调度器(最新推荐)

《深入理解ApacheAirflow调度器(最新推荐)》ApacheAirflow调度器是数据管道管理系统的关键组件,负责编排dag中任务的执行,通过理解调度器的角色和工作方式,正确配置调度器,并... 目录什么是Airflow 调度器?Airflow 调度器工作机制配置Airflow调度器调优及优化建议最

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

Redis与缓存解读

《Redis与缓存解读》文章介绍了Redis作为缓存层的优势和缺点,并分析了六种缓存更新策略,包括超时剔除、先删缓存再更新数据库、旁路缓存、先更新数据库再删缓存、先更新数据库再更新缓存、读写穿透和异步... 目录缓存缓存优缺点缓存更新策略超时剔除先删缓存再更新数据库旁路缓存(先更新数据库,再删缓存)先更新数

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规