实际操作理解 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

相关文章

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

【Linux】应用层http协议

一、HTTP协议 1.1 简要介绍一下HTTP        我们在网络的应用层中可以自己定义协议,但是,已经有大佬定义了一些现成的,非常好用的应用层协议,供我们直接使用,HTTP(超文本传输协议)就是其中之一。        在互联网世界中,HTTP(超文本传输协议)是一个至关重要的协议,他定义了客户端(如浏览器)与服务器之间如何进行通信,以交换或者传输超文本(比如HTML文档)。

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中, "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时,经常听到第一范式(1NF)、第二范式(2NF)、第三范式(3NF)以及 BCNF(Boyce-Codd范式)。这些范式都旨在通过消除数据冗余和异常来优化数据库结构。然而,当我们谈到 4NF(第四范式)时,事情变得更加复杂。本文将带你深入了解 多值依赖 和 4NF,帮助你在数据库设计中消除更高级别的异常。 什么是

如何确定 Go 语言中 HTTP 连接池的最佳参数?

确定 Go 语言中 HTTP 连接池的最佳参数可以通过以下几种方式: 一、分析应用场景和需求 并发请求量: 确定应用程序在特定时间段内可能同时发起的 HTTP 请求数量。如果并发请求量很高,需要设置较大的连接池参数以满足需求。例如,对于一个高并发的 Web 服务,可能同时有数百个请求在处理,此时需要较大的连接池大小。可以通过压力测试工具模拟高并发场景,观察系统在不同并发请求下的性能表现,从而