初窥 HTTP 缓存
引言
对于前端来说, 你肯定听说过 HTTP
缓存。 当然不管你知不知道它, 对于提高网站性能和用户体验, 它都扮演着重要的角色! 它通过在客户端和服务器之间存储和重用先前获取的资源副本, 来减少网络流量和降低资源加载时间, 从而提升用户体验! 以下是 HTTP
缓存的重要性:
- 减少加载时间: 通过使用缓存, 浏览器可以重用已下载的资源, 而不必每次都从服务器重新请求。这减少了页面加载时间, 提高了用户体验, 尤其是在较慢的网络连接下
- 降低服务器负载:
HTTP
缓存可以减少服务器的负载, 因为不再需要为相同的资源处理大量重复请求。这有助于减少服务器资源的使用, 降低运营成本 - 减少网络流量:
HTTP
缓存可以减少不必要的网络流量, 因为浏览器可以从本地缓存中加载资源, 而不必每次都从服务器下载。这有助于减少带宽成本, 尤其是对于大型网站来说 - 提高用户体验: 快速加载的网页提供更好的用户体验, 吸引更多的访问者, 并增加用户留存率。缓存使用户能够更快地访问网站内容, 从而提高了他们的满意度
实际开发中我们有时为了避免因为缓存导致资源没有更新, 常常会简单而粗暴的为资源文件路径添加一个时间戳! 该方式虽然有效, 也能解决实际问题, 但过于粗暴了, 我们完全可以采用更加优雅的方式。本文将对 HTTP
缓存进行一个详细的讲解, 来帮助大家对 HTTP
缓存有一个较深的理解, 帮忙大家在实际项目中设计出更为合理、高效的缓存方案!!
补充(偶然看到一句话, 送给大家): 所有的技术都是为了解决问题而存在的, 在不了解问题情况下强行记忆, 效果肯定是打折扣的!!
本文使用到的
DEMO
地址点 这里
一、强缓存
首先在上文我们已经强调了 HTTP
缓存的一个重要性, 那么要想设计一个缓存方案, 最简单的办法就是根据资源加载的时间:
- 首次加载资源时将资源缓存起来
- 然后在指定时间内如果加载同一份资源, 则客户端(浏览器)直接使用缓存数据, 而不向服务器发起任何请求
- 当然如果超时则会发起新的请求获取资源, 然后再次缓存起来
而这种不发起任何请求(没经过服务端), 直接由客户端(浏览器)自行决定是否使用缓存的方案, 则被称为 强缓存
!!
1.1 Expires
Expires
响应头, 表示当前获取到的资源的过期时间, 该时间是一个 GMT
时间, 即格林尼治时间!!
当客户端(浏览器)再次获取资源前:
- 如果
存在未到期
的缓存资源, 则直接获取缓存的资源, 不发起任何请求!! - 如果
不存在缓存资源
或者缓存的资源已过期
, 则向服务器发起请求获取资源, 并再次缓存资源
特别注意的是, Expires
是 HTTP/1.0
的产物了, 现在大部分浏览器均默认使用 HTTP/1.1
所以它的作用基本可以忽略!!
但这里其实有一个问题, Expires
时间是由服务端生成的, 这时如果客户端时间跟服务器时间不一致, 就会导致缓存命中的误差!!
所以后面就有了 Cache-Control
…
1.2 Cache-Control
Cache-Control
响应头, HTTP/1.1
出现的一个响应头, 它弥补了 Expires
的缺陷:
Expires
是直接由服务端给定一个资源过期时间Cache-Control
则不同, 服务端只会告诉客户端该资源的有效期! 就比如, 它有一个max-age
字段, 当它被设置为10
, 则表示当前资源有效期为10
秒,10
秒过后资源缓存将失效
Cache-Control
相对来说使用起来也更为复杂, 可设置的属性也比较多。当然复杂也说明它可适用于更广泛的复杂场景, 下面我们来看下 Cache-Control
响应头的语法规则:
- 不区分大小写, 但建议使用小写
- 多个指令以逗号分隔
- 具有可选参数, 可以用令牌或者带引号的字符串语法
Cache-Control
可选属性有: 注意 no-cache
和 no-store
的区别, no-store
才是禁用 强缓存
类型 | 属性 | 描述 |
---|---|---|
可缓存性 | public | 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)缓存 |
可缓存性 | private | 私有缓存, 响应只能被单个客户端缓存 |
可缓存性 | no-cache | 无论本地缓存是否过期, 都需要请求源服务器进行验证(协商缓存验证) |
可缓存性 | no-store | 不使用任何缓存 |
到期时间 | max-age=<seconds> | 设置缓存有效期的最大周期, 超过这个时间缓存被认为过期(单位秒) |
到期时间 | s-maxage=<seconds> | 同 max-age , 但是仅适用于共享缓存(代理服务器), 生效时会覆盖 max-age 或者 Expires |
到期时间 | max-stale[=<seconds>] | 表明客户端愿意接收一个已经过期的资源, 可以设置一个可选的秒数, 表示缓存允许过期的最大值 |
到期时间 | min-fresh=<seconds> | 希望在一个指定的秒数内保持资源的最新, 也就是说在设定的时间内获取资源不管缓存有没效, 都需要发起缓存进行验证(协商缓存验证) |
到期时间 | stale-while-revalidate=<seconds> | 实验版, 有点类似 max-stale , 客户端愿意接收一个已经过期的资源, 同时客户端会在后台异步获取新的资源; 可以设置一个秒数, 表示允许接受陈旧缓存的最大值 |
到期时间 | stale-if-error=<seconds> | 实验版, 如果新的检查失败, 则客户端愿意接受陈旧的响应, 设置的秒数值表示客户端在初始到期后愿意接受陈旧响应的时间 |
重新验证或重新加载 | must-revalidate | 如果本地副本未过期, 可以使用本地副本; 否则, 需要请求源服务器进行验证 |
重新验证或重新加载 | proxy-revalidate | 与 must-revalidate 作用相同, 但它仅适用于共享缓存(例如代理服务器), 对于私有缓存(本地缓存)该值会被忽略 |
重新验证或重新加载 | immutable | 实验版, 表示缓存一直有效, 再也不会发起请求了 |
其他 | no-transform | 不允许对资源进行转换或转变, Content-Encoding 、Content-Range 、Content-Type 等 HTTP 头允许被代理服务修改 |
其他 | only-if-cached | 客户端只接受已缓存的响应, 不会进行任何请求, 如果缓存不命中则返回错误 |
下面我们来测试下, 如下代码是使用 Koa
搭建的一个简单服务:
- 代码中实现了一个
GET
接口/api/cache-control
- 在接口
/api/cache-control
响应体中设置了Cache-Control
响应头, 值为public,max-age=120
- 那么当客户端访问
/api/cache-control
理论上, 请求的响应内容会被任何端缓存起来, 缓存有效期120s
const Koa = require('koa');
const moment = require('moment');
const cors = require('@koa/cors')
const Router = require('@koa/router');const app = new Koa();
const router = new Router();// 跨域设置
app.use(cors({maxAge: 5,origin: "*",credentials: true,allowMethods: ['GET', 'POST'],allowHeaders: ['Content-Type'],exposeHeaders: ['Content-Type'],
}));// 2. Cache-Control
router.get('/api/cache-control', async (ctx) => {ctx.status = 200;ctx.body = 111111111;ctx.set('Cache-Control', `public,max-age=120`);
});app.use(router.routes()).use(router.allowedMethods());
app.listen(3000);
1.3 Pragma
Pragma
是一个在 HTTP/1.0
中规定的响应头, 它只有一个属性值, 就是 no-cache
, 其效果和 Cache-Control
中的 no-cache
是一致的, 表明不使用强缓存, 需要客户端(浏览器)与服务器验证缓存是否有效, Pragma
在本节的 3
个头部属性中的优先级是最高的
也许你会奇怪为啥有了 Cache-Control
还要整个 Pragma
, 这里你需要注意的是 Cache-Control
其实是后面 HTTP/1.1
才出来的, 在 Cache-Control
之前 Pragma
是作为 Expires
的一个补充!!
当然 Pragma
目前主要就是用于向后兼容那些只支持 HTTP/1.0
协议的客户端!!
二、协商缓存
上文几个响应头, 客户端、服务端是通过约定缓存有效时间来决定, 是否 直接
使用本地缓存!! 但是这个方案其实存在很明显的问题:
- 假设我们约定每次资源缓存的有效时间为
2
分钟 - 但是呢?
2
分钟内, 如果服务端资源更新了, 按强缓存来, 这时客户端拿到的资源都是缓存内容, 就无法保证资源的最新 - 同样, 如果服务端资源一直不更新, 那么
2
分钟后, 客户端如果发起请求这时将会重新获取资源, 这就不可避免的造成资源的浪费
那么要想解决上面这个问题, 就可以使用 协商缓存
, 其实所谓 协商缓存
就是客户端(浏览器)在请求资源时先向服务端进行 协商
: 客户端(浏览器)向服务端询问本地缓存的资源是否是最新的
- 如果本地缓存的资源
未过期
, 那么服务端就会将请求状态码设置为304
(Not Modified
), 这时请求不会返回任何body
, 客户端(浏览器)将直接使用本地缓存 - 如果本地缓存已过期, 那么服务端正常处理请求, 状态码设置为
200
, 这时的body
将是完整的资源内容
那么服务端如何判断客户端本地的缓存不是最新的呢? 它们之间又是怎么协调的呢?
2.1 Last-Modified / If-Modified-Since
第一个方案其实就是根据 资源最后修改时间
来进行判断:
- 当客户端首次请求资源时, 服务端会把资源的最后修改时间放到
Last-Modified
响应头中(浏览器自动将Last-Modified
也缓存起来) - 当客户端再次请求资源时, 浏览器会通过
If-Modified-Since
请求头, 将本地缓存资源对应最后修改时间带上(这个是浏览器自己的行为, 不需要我们认为去处理) - 服务端就可以根据
If-Modified-Since
来判断客户端(浏览器)的资源是否是最新的 - 如果是客户缓存的资源是最新的, 则
body
直接返回空, 同时将状态码改为304
(Not Modified
) - 否则按首次请求资源处理, 状态码为
200
,body
为请求的资源内容
下面使用 Koa
搭建的一个简单服务:
- 在接口中我们将客户端请求头中的
if-modified-since
和当前的Last-Modified
进行比较 - 如果相同, 则表示客户端的资源是最新的, 则不返回任何内容(
body
为空), 让客户端直接使用缓存(状态码设置为304
) - 如果不相同, 则表示客户端的资源不是最新的, 则正常返回内容(状态码为
200
,body
为当前资源内容), 当然这时还需要带上Last-Modified
const Koa = require('koa');
const moment = require('moment');
const cors = require('@koa/cors')
const Router = require('@koa/router');const app = new Koa();
const router = new Router();// 跨域设置
app.use(cors({maxAge: 5,origin: "*",credentials: true,allowMethods: ['GET', 'POST'],allowHeaders: ['Content-Type'],exposeHeaders: ['Content-Type'],
}));// 4. Last-Modified / If-Modified-Since
const lastModified = 'Thu, 09 Nov 2023 06:37:41 GMT'
router.get('/api/last-modified', async (ctx) => {// 客户端本地缓存最新更改时间和当前的一致 => 让客户端直接使用缓存吧if (ctx.request.header['if-modified-since'] === lastModified) {ctx.status = 304;ctx.body = '2222'} else {// 返回最新内容ctx.status = 200;ctx.body = '111111111'}ctx.set('Last-Modified', lastModified);ctx.set('Cache-Control', 'no-cache');
});app.use(router.routes()).use(router.allowedMethods());app.listen(3000);
这里有个奇怪的现象, 第二次请求时, 服务器实际上设置的状态码为 304
, body
内容为 2222
, 但是在 chrome
中查看的话会发现展示出来的状态码为 200
, body
为缓存的数据!!
猜测: chrome
针对本地存在缓存的 304
接口做了处理, 这里有一篇文章可供参考 《为什么Chrome开发工具显示200状态代码而不是 304? 》, 具体原因就不细究了…
2.2 ETag / If-None-Match
「根据最后修改时间, 来判定客户端缓存是否是最新的资源」这个依据在大部分情况应该是有效的!! 但是也避免不了一种情况就是, 资源更新时间变了, 但是呢内容和之前却是一样的(比如项目重新打包、资源修改一版又撤销回去…)
这种情况下, 我们就可以使用 ETag
来判断资源是否有效!!! ETag
作为资源内容的唯一标记被使用, 它可以是资源内容对应的一个唯一 ID
, 也可以是根据资源文件内容生成的一个 MD5
, 总之它代表的当前资源的一个唯一值!!
ETag
在服务端和客户端之前的工作流程和 Last-Modified
基本一致:
- 当客户端首次请求资源时, 服务端会把当前资源对应唯一标记放到
ETag
响应头中(浏览器会将ETag
也缓存起来) - 当客户端再次请求资源时, 浏览器会通过
If-None-Match
请求头, 将本地缓存资源对应的ETag
带上(浏览器自己的行为) - 服务端就可以根据
If-None-Match
以及当前资源的ETag
来判断客户端(浏览器)的资源是否是最新的 - 如果客户缓存的资源是最新的, 则
body
直接返回空, 同时将状态码改为304
(Not Modified
) - 否则按首次请求资源处理, 同时带上
ETag
下面使用 Koa
搭建的一个简单服务:
- 在接口中我们将客户端请求头中的
if-none-match
和当前的ETag
进行比较 - 如果相同, 则表示客户端的资源是最新的, 则不返回任何内容(
body
为空), 让客户端直接使用缓存(状态码设置为304
) - 如果不相同, 则表示客户端的资源不是最新的, 则正常返回内容(状态码为
200
,body
为当前资源内容), 当然这时还需要带上ETag
const Koa = require('koa');
const moment = require('moment');
const cors = require('@koa/cors')
const Router = require('@koa/router');const app = new Koa();
const router = new Router();// 跨域设置
app.use(cors({maxAge: 5,origin: "*",credentials: true,allowMethods: ['GET', 'POST'],allowHeaders: ['Content-Type'],exposeHeaders: ['Content-Type'],
}));// 5. ETag / If-None-Match
const ETag = '33a64df551425fcc55e4d42a148795d9f25f89d4'
router.get('/api/etag', async (ctx) => {// 客户端本地缓存最新 ETag 和当前的一致 => 让客户端直接使用缓存吧if (ctx.request.header['if-none-match'] === ETag) {ctx.status = 304;ctx.body = '2222'} else {// 返回最新内容ctx.status = 200;ctx.body = '111111111'}ctx.set('ETag', ETag);ctx.set('Cache-Control', 'no-cache');
});app.use(router.routes()).use(router.allowedMethods());app.listen(3000);
同上文, 如果本地缓存有效, 并且服务端状态码为
304
,chrome
展示状态码也只会是200
, 内容为缓存的内容
2.3 补充: If-Unmodified-Since / If-Match
上文提到的几个消息头, 都只是在获取资源(get
请求)情况下生效!! If-Unmodified-Since
和 If-Match
则是在修改内容的情况下生效, 比如 post
、put
、remove
等请求:
- 当客户端(浏览器)发起请求试图修改资源时, 可以携带上
If-Unmodified-Since(本地资源对应 Last-Modified)
或If-Match(本地资源 ETag)
- 服务端通过请求头中的
If-Unmodified-Since
或If-Match
来判断服务端资源是否已经被修改过(当前本地资源是否是最新的) - 如果服务端的资源已经被修改过, 那么服务端直接返回
412
(Precondition Failed
) 错误, 不处理本次请求 - 相反, 则返回
200
! 正常处理请求
三、优先级
- 首先强缓存优先级大于协商缓存, 只有在强缓存失效情况下, 然后才会和服务端建立连接进行协商
- 强缓存中:
Pragma
>Cache-Control
>Expires
- 协商缓存中:
ETag
>Last-Modified
, 因为ETag
更为精准
四、参考
- 30分钟搞懂 HTTP 缓存
- 前端应该知道 HTTP 缓存机制
- 从未如此简单 5 分钟搞懂 HTTP 缓存机制
- 彻底搞懂 HTTP 缓存策略,切记死背概念!
- HTTP 缓存看这一篇就够了
- 图解 HTTP 缓存
- 轻松理解 HTTP 缓存策略
- 面试官: 你懂 HTTP 缓存,那说下浏览器强制刷新是怎么实现的?
相关文章:
初窥 HTTP 缓存
引言 对于前端来说, 你肯定听说过 HTTP 缓存。 当然不管你知不知道它, 对于提高网站性能和用户体验, 它都扮演着重要的角色! 它通过在客户端和服务器之间存储和重用先前获取的资源副本, 来减少网络流量和降低资源加载时间, 从而提升用户体验! 以下是 HTTP 缓存的重要性: 减少…...
【LeetCode】3. 哈希表: 字母异位词分组;有效的数独
题目 字母异位词分组 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [[“…...
设计模式之抽象工厂 C# 范例
在设计模式中,抽象工厂模式(Abstract Factory Pattern) 是一种创建型模式,它提供一个接口,用于创建一组相关或相互依赖的对象,而无需指定具体类。这种模式的关键在于通过抽象工厂来封装产品的创建ÿ…...
基于Python的猎聘网招聘数据采集与可视化分析
1.1项目简介 在现代社会,招聘市场的竞争日趋激烈,企业和求职者都希望能够更有效地找到合适的机会与人才。猎聘网作为国内领先的人力资源服务平台,汇聚了大量的招聘信息和求职者数据,为研究招聘市场趋势提供了丰富的素材。基于Pyt…...
oracle数据库的启动与关闭
一.oracle数据库的启动过程 启动实例(Start the Instance) 启动实例:一个Oracle数据库实例由内存结构和后台进程组成,启动实例时会加载这些内存结构和启动进程。实例是数据库的一个运行时环境,它包含了数据库的控制文…...
openGauss开源数据库实战十六
文章目录 任务十六 openGauss逻辑结构:触发器管理任务目标实施步骤一、测试openGauss的触发器1.创建测试表2.创建触发器对应的函数3.创建触发器4.测试触发器 二、触发器的类型1.行级触发器2.语句级触发器3.AFTER触发器和 BEFORE触发器 任务十六 openGauss逻辑结构:触发器管理 …...
智能教育的关键之一是构建智能学习系统
教育部办公厅12月27日发布《关于加强中小学人工智能教育的通知》,提出人工智能教育六大主要任务和举措,包括构建系统化课程体系、实施常态化教学与评价、开发普适化教学资源、建设泛在化教学环境、推动规模化教师供给和组织多样化交流活动。《通知》提出…...
【Linux 篇】Docker 容器星河与镜像灯塔:Linux 系统下解锁应用部署奇幻征程
文章目录 【Linux 篇】Docker 容器星河与镜像灯塔:Linux 系统下解锁应用部署奇幻征程前言一 、docker上部署mysql1. 拉取mysql镜像2. 创建容器3. 远程登录mysql 二 、docker上部署nginx1. 拉取nginx镜像2. 在dockerTar目录下 上传nginx.tar rz命令3. 创建nginx容器4…...
十四(AJAX)、AJAX、axios、常用请求方法(GET POST...)、HTTP协议、接口文档、form-serialize
1. AJAX介绍及axios基本使用 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content&q…...
雪花算法生成ID
下面将简单介绍雪花算法的简单应用和在web应用中的使用。 雪花算法的组成:雪花算法是由64位组成:符号位(1)、时间戳(41)、机器码(5[数据中心]5[机器ID])、计数器(12) 对于雪花算法的源码可以在这里看:bwmarrin/snowflake: A simple to use …...
Java - JSR223规范解读_在JVM上实现多语言支持
文章目录 1. 概述2. 核心目标3. 支持的脚本语言4. 主要接口5. 脚本引擎的使用执行JavaScript脚本执行groovy脚本1. Groovy简介2. Groovy脚本示例3. 如何在Java中集成 Groovy4. 集成注意事项 6. 与Java集成7. 常见应用场景8. 优缺点9. 总结 1. 概述 JSR223(Java Spe…...
vue3 基本使用
Vue 3 提供了多种方式来构建用户界面,包括选项式 API 和 Composition API。下面我将详细介绍 Vue 3 的基本使用和语法,主要集中在选项式 API 上,因为这对于初学者来说更容易上手。 1. 创建 Vue 项目 如果你还没有一个 Vue 项目,…...
Redis自学之路—高级特性(实现消息队列)(七)
目录 简介 Redis的Key和Value的数据结构组织 全局哈希表 渐进式rehash 发布和订阅 操作命令 publish 发布消息 subscribe 订阅消息 psubscribe订阅频道 unsubscribe 取消订阅一个或多个频道 punsubscribe 取消订阅一个或多个模式 查询订阅情况-查看活跃的频道 查询…...
ROS基本框架2——在ROS开发中创建并使用自定义消息(C++版本)
ROS基本框架2——在ROS开发中创建并使用自定义消息(C++版本) code review! 参考笔记 1.ROS基本框架1——编写简单的发布者和订阅者(C++和Python版本) 2.ROS基本框架2——在ROS开发中创建并使用自定义消息(C++版本) 文章目录 ROS基本框架2——在ROS开发中创建并使用自定义…...
计算机的错误计算(一百七十二)
摘要 探讨 MATLAB 对于算式 的计算误差。 例1. 在 MATLAB 中计算 的值。 直接贴图吧: 这样,MATLAB 的输出中只有3位正确数字,有效数字的错误率为 (16-3)/16 81.25% . 因为16位的正确输出为 0.2971242332737277e-18(ISReals…...
贵州大学oj平台高级语言第九次作业(四)
题目:链表的基础操作 题目描述 链表是软件中一种最基本的数据结构,它是用链式存储结构实现数据存储的线性表。它较顺序表(如数组)而言在插入和删除数据时不必移动其后的大批量元素。现在给你一些整数,然后会频繁地插入和删除其中的某些元素&a…...
手机卡限速丨中国移动5G变3G,网速500kb
以下猜测错误,又有新的猜测:河南移动的卡出省限速。可能是因为流量结算。 “2024年7月1日起,中国移动集团内部将开启跨省流量结算” 在深圳四五年了,之前没有过,就从上个月开始。11月底解除限速,12月刚开…...
种花问题算法
假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。 给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 …...
Node.js-Mongodb数据库
MongoDB MongoDB是什么? MongoDB是一个基于分布式文件存储的数据库 数据库是什么? 数据库(DataBase)是按照数据结构来组织、存储和管理数据的应用程序(软件) 数据库作用? 对数据进行增、删…...
Nginx
目录 基本介绍 Nginx核心功能 Nginx下载&安装&启动 配置防火墙 Nginx常用命令 Nginx配置文件 全局块 events块 http块 http全局块 server 块 检查配置信息 快速入门 安装JDK 安装Tomcat 反向代理分析 Location语法规则 反向代理配置-Location实例 …...
CTF-PWN: 全保护下格式化字符串利用 [第一届“吾杯”网络安全技能大赛 如果能重来] 赛后学习(没思路了)
通过网盘分享的文件:如果能重来.zip 链接: https://pan.baidu.com/s/1XKIJx32nWVcSpKiWFQGpYA?pwd1111 提取码: 1111 --来自百度网盘超级会员v2的分享漏洞分析 格式化字符串漏洞,在printf(format); __int64 sub_13D7() {char format[56]; // [rsp10h] [rbp-40h]…...
HTML5系列(7)-- Web Storage 实战指南
前端技术探索系列:HTML5 Web Storage 实战指南 🗄️ 致读者:本地存储的新纪元 👋 前端开发者们, 今天我们将深入探讨 HTML5 中的 Web Storage 技术,这是一个强大的本地存储解决方案,让我们能…...
RocketMQ: 保证消息的可靠性投递
概述 在分布式系统中,消息队列作为异步通信的重要组件,其可靠性和稳定性至关重要RocketMQ 是阿里巴巴开源的一款高性能、高可靠性的分布式消息中间件,广泛应用于各种场景,如交易订单处理、日志收集、流计算等 RocketMQ 的可靠性…...
消息传递神经网络(Message Passing Neural Networks, MPNN)
消息传递神经网络(Message Passing Neural Networks, MPNN) 一、引言二、消息传递框架概述1.消息传递阶段(1)消息生成与传播-message(2)消息聚合-aggregate(3)消息更新-update&#…...
Python干货总结篇:列表、字典、集合、元组的区别与用途
前言: 更详细知识点,搞懂列表、字典、集合、元组到底是什么,可关注主页文章:Python知识点精汇! 目录 一、特点与用途 1.列表:a[ ] 2.集合:a{ } 3.字典:a{key:value} 4.元组&am…...
vue.js学习(day 18)
实例:面经基础版...
【Gitlab】CICD使用minio作为分布式缓存
1、安装minio 下载适合自己系统版本的安装文件https://dl.min.io/server/minio/release/windows-amd64/ yum install xxx.rpm 2、配置/etc/profile export MINIO_ACCESS_KEYroot [ui登录账号] export MINIO_SECRET_KEYminioDev001 [ui登录密码] export MINIO_OPTS"…...
医院管理系统
私信我获取源码和万字论文,制作不易,感谢点赞支持。 医院管理系统 摘要 随着信息互联网信息的飞速发展,医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求,创建了一个计…...
编译器优化技术
方法内联 逃逸分析 公共子表达式消除 数据边界检查消除...
高斯消元——acwing
题目一:高斯消元解线性方程组 883. 高斯消元解线性方程组 - AcWing题库 分析 代码 #include<bits/stdc.h> using namespace std;const int N 110; const double eps 1e-6; // 注意了double, 和1e-6 ,,这样才是double的0 int n;double a[N][N];int guass…...
华为关键词覆盖应用市场ASO优化覆盖技巧
在我国的消费者群体当中,华为的品牌形象较高,且产品质量过硬,因此用户基数也大。与此同时,随着影响力的增大,华为不断向外扩张,也逐渐成为了海外市场的香饽饽。作为开发者和运营者,我们要认识到…...
[代码随想录06]哈希表的使用,有效字母异位词,两数组交集,快乐数,两数之和
前言 哈希表是什么?一句话带你理解,简单来说我们对于杂乱的数据,怎么快速找到数据,如何做呢?一般的做法就是遍历复杂度为o(N)去找寻一个数据,但是吧,我们这样思考的话,还是花了大量时…...
linux网络抓包工具
linux网络抓包工具 一、tcpdump1.1 基本用法1.2 龙芯平台实例操作 二、wireshark2.1 主要功能2.2 龙芯平台实例操作 一、tcpdump tcpdump 指令可列出经过指定网络界面的数据包文件头,可以将网络中传送的数据包的 “头” 完全截获下来提供分析。它支持针对网络层、协…...
运维工程师.云计算工程师面试题.考试题
《(全国)运维自动化阶段第1套卷》 卷面总分 题号 单选题 90 题分 得分 一、单选题(每题2分,共计70分;得分____) 1. 下面哪个选项可以做变量名称?( ) A、if B、123abc C、for D、User_Name 2. 哪种数据类型可以做增,删,改相关操作?( ) A、字符串 B、列表 C、元…...
递归1——递归入门
目录 1.递归 2.递归的基本题目 2.1.题目一——P5739 【深基7.例7】计算阶乘 - 洛谷 | 计算机科学教育新生态 2.2.题目二——B2064 斐波那契数列 - 洛谷 | 计算机科学教育新生态 2.3.题目三——B2142 求 123...N 的值 - 洛谷 | 计算机科学教育新生态 2.4.题目四——B2144…...
XuperChain核心流程
04-XuperChain核心流程 0 XuperChain架构图 核心框架 Xuper Chain主要由 Xuper Core 这个核心引擎来构建。Xuper Core 分为三个部分: 基础组件:日志、存储、监控等关键组件,以及密码学库等基本组件。 核心组件:包括共识、合约、账…...
2024.12.2工作复盘
1.今天学了什么? 简单的写了一篇博客,是关于参数校验的问题,参数校验,一个是前后端校验到底一不一致,一个是绕过前端校验,看后台的逻辑到底能不能校验住。 2.今天解决了什么问题? 3.今天完成…...
关于Vscode配置Unity环境时的一些报错问题(持续更新)
第一种报错: 下载net请求超时(一般都会超时很正常的) 实际时并不需要解决,它对你的项目毫无影响 第二种报错: .net版本不匹配 解决:(由于造成问题不一样,所以建议都尝试一次&…...
微信小程序——文档下载功能分享(含代码)
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
长短期记忆网络 (LSTM) 简介
文章目录 一、说明二、传统 RNN 的问题三、为什么梯度消失?四、长短期记忆网络简介五、忘记门六、Update Gate (Input Gate)七、Output Gate八、数学上的内存九、从 LSTM 到 Transformer十、总结 一、说明 机器学习取得进步的领域之一是自然语言处理。对于用于机器…...
【电子通识】USB Type-C线缆为什么有的用到E-Marker芯片
USB Type-C接口具备数据传输、充电(基于USB PD协议)和音频视频传输能力。但是,上述功能都有强弱之别,并因此衍生出了无数种规格的USB Type-C线缆。 如下所示直接搜索就可以看到,虽然都是Type-C接口,但存在很多不同种类的线缆规格。 以数据传输为例,USB Type-C可选USB2.0…...
【故障处理系列--移动云云盘根目录在线扩容】
移动云云盘根目录扩容 **目的:**测试harbor仓库服务器的根目录能否在线扩容 1、移动云控制台系统盘扩容 这里以我自己的虚拟机演示 2、查看分区的文件类型 3、安装growpart工具 rootgitlab-cli:~# apt install cloud-guest-utils -y rootgitlab-cli:~# apt ins…...
混沌工程/混沌测试/云原生测试/云平台测试
背景 私有云/公有云/混合云等具有复杂,分布式,环境多样性等特点,许多特殊场景引发的线上问题很难被有效发现。所以需要引入混沌工程,建立对系统抵御生产环境中失控条件的能力以及信心,提高系统面对未知风险得能力。 …...
CQ 社区版 2024.11 | 新增“审批人组”概念、可通过SQL模式自定义审计图表……
CloudQuery 社区 11 月新版本来啦!本月版本依旧是 CUG(CloudQuery 用户组)尝鲜版的更新。 针对审计模块增加了 SQL 模式自定义审计图表;在流程模块引入了“审批人组”概念。此外,在 SQL 编辑器、连接管理等模块都涉及…...
【maven-4】IDEA 配置本地 Maven 及如何使用 Maven 创建 Java 工程
IntelliJ IDEA(以下简称 IDEA)是一款功能强大的集成开发环境,广泛应用于 Java 开发。下面将详细介绍如何在 IDEA 中配置本地 Maven,并创建一个 Maven Java 工程,快速上手并高效使用 Maven 进行 Java 开发。 1. Maven …...
c语言结构体
c语言结构体 1. 结构体的定义 在C语言中,结构体是一种用户自定义的数据类型,它允许你将不同类型的数据组合成一个单一的实体。结构体的定义以struct关键字开头,后面跟着结构体标签(可以省略,但为了方便后续引用&#…...
洛谷二分题
P1024 [NOIP2001 提高组] 一元三次方程求解 题目描述 有形如:𝑎𝑥3𝑏𝑥2𝑐𝑥𝑑0ax3bx2cxd0 这样的一个一元三次方程。给出该方程中各项的系数(𝑎,ᵄ…...
vue3的项目目录和关键文件
注意换插件 vue2的是 Vetur ;vue3的是volar 这里注意volar插件已更名为Vue - Official vite.config.js 放跟vite配置相关的内容 区别于vue2;vue2是vue.config.js;vue2是基于webpack的,vue3是基于vite的 main.js import { creat…...
rabbitmq原理及命令
目录 一、RabbitMQ原理1、交换机(Exchange)fanoutdirecttopicheaders(很少用到) 2、队列Queue3、Virtual Hosts4、基础对象 二、RabbitMQ的一些基本操作:1、用户管理2、用户角色3、vhost4、开启web管理接口5、批量删除队列 一、Ra…...
洛谷 P1308 [NOIP2011 普及组] 统计单词数 C语言
题目: https://www.luogu.com.cn/problem/P1308 复制Markdown 展开 题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。 现在,请你编程实现…...