项目部署之后页面没有刷新怎么办?

最近项目部署成功之后,突然产品找我,上线之后,页面没有生效,这是怎么回事?我这是第一次部署这个项目,也不太清楚历史问题,接下来就慢慢寻找答案吧, 如果心急的可以直接看后面的总结,下面我们好好聊聊缓存的问题。

浏览器输入url之后,就会进行下面一系列判断,来实现页面渲染。

首先讲一下常见的http缓存~

HTTP缓存常见的有两类:

  • 强缓存:可以由这两个字段其中一个决定
    • expires
    • cache-control(优先级更高)
  • 协商缓存:可以由这两对字段中的一对决定
    • Last-Modified,If-Modified-Since
    • Etag,If-None-Match(优先级更高)

强缓存

使用的是express框架

expires

app.get('/login', function(req, res){// 设置 Expires 响应头const time = new Date(Date.now() + 300000).toUTCString()res.header('Expires', time)res.render('login');
});

然后我们在前端页面刷新,我们可以看到请求的资源的响应头里多了一个expires的字段, 取消Disable cache

刷新

勾选Disable cache

但是,Expires已经被废弃了。对于强缓存来说,Expires已经不是实现强缓存的首选。

因为Expires判断强缓存是否过期的机制是:获取本地时间戳,并对先前拿到的资源文件中的Expires字段的时间做比较。来判断是否需要对服务器发起请求。这里有一个巨大的漏洞:“如果我本地时间不准咋办?”

是的,Expires过度依赖本地时间,如果本地与服务器时间不同步,就会出现资源无法被缓存或者资源永远被缓存的情况。所以,Expires字段几乎不被使用了。现在的项目中,我们并不推荐使用Expires,强缓存功能通常使用cache-control字段来代替Expires字段。

cache-control

其实cache-control跟expires效果差不多,只不过这两个字段设置的值不一样而已,前者设置的是秒数,后者设置的是毫秒数

app.get('/login', function(req, res){// 设置 Expires 响应头// const time = new Date(Date.now() + 300000).toUTCString()// res.header('Expires', time)// 设置 Cache-Control 响应头res.header('Cache-Control', 'max-age=300')res.render('login');
});

前端页面响应头多了cache-control这个字段,且300s内都走本地缓存,不会去请求服务端

Cache-Control:max-age=N,N就是需要缓存的秒数。从第一次请求资源的时候开始,往后N秒内,资源若再次请求,则直接从磁盘(或内存中读取),不与服务器做任何交互。

Cache-control中因为max-age后面的值是一个滑动时间,从服务器第一次返回该资源时开始倒计时。所以也就不需要比对客户端和服务端的时间,解决了Expires所存在的巨大漏洞。

Cache-control的多种属性:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control

但是使用最多的就是no-cache和no-store,接下来就重点学习这两种

no-cache和no-store

no_cache是Cache-control的一个属性。它并不像字面意思一样禁止缓存,实际上,no-cache的意思是强制进行协商缓存。如果某一资源的Cache-control中设置了no-cache,那么该资源会直接跳过强缓存的校验,直接去服务器进行协商缓存。而no-store就是禁止所有的缓存策略了。

app.get('/login', function(req, res){// 设置 Expires 响应头// const time = new Date(Date.now() + 300000).toUTCString()// res.header('Expires', time)// 设置 Cache-Control 响应头res.header('Cache-Control', 'no-cache')res.render('login');
});

no-cache(进行协商缓存,下次再次请求,没有勾选控制台Disable cache,状态码是304)

app.get('/login', function(req, res){// 设置 Cache-Control 响应头res.header('Cache-Control', 'no-store')res.render('login');
});

no-store(每次都请求服务器的最新资源,没有缓存策略)

强制缓存就是以上这两种方法了。现在我们回过头来聊聊,Expires难道就一点用都没有了吗?也不是,虽然Cache-control是Expires的完全替代品,但是如果要考虑向下兼容的话,在Cache-control不支持的时候,还是要使用Expires,这也是我们当前使用的这个属性的唯一理由。

协商缓存

与强缓存不同的是,强缓存是在时效时间内,不走服务端,只走本地缓存;而协商缓存是要走服务端的,如果请求某个资源,去请求服务端时,发现命中缓存则返回304,否则则返回所请求的资源,那怎么才算命中缓存呢?接下来讲讲

Last-Modified,If-Modified-Since

简单来说就是:

  • 第一次请求资源时,服务端会把所请求的资源的最后一次修改时间当成响应头中Last-Modified的值发到浏览器并在浏览器存起来
  • 第二次请求资源时,浏览器会把刚刚存储的时间当成请求头中If-Modified-Since的值,传到服务端,服务端拿到这个时间跟所请求的资源的最后修改时间进行比对
  • 比对结果如果两个时间相同,则说明此资源没修改过,那就是命中缓存,那就返回304,如果不相同,则说明此资源修改过了,则没命中缓存,则返回修改过后的新资源

基于last-modified的协商缓存实现方式是:

  1. 首先需要在服务器端读出文件修改时间,
  2. 将读出来的修改时间赋给响应头的last-modified字段。
  3. 最后设置Cache-control:no-cache

三步缺一不可。

app.get('/login', function(req, res){// 设置 Expires 响应头// const time = new Date(Date.now() + 300000).toUTCString()// res.header('Expires', time)const { mtime } = fs.statSync(path.join(__dirname, 'public/index.css')) // 读取最后修改时间console.log(mtime.toUTCString(), '--------')// 响应头的last-modified字段res.header('last-modified', mtime.toUTCString())// 设置 Cache-Control 响应头res.header('Cache-Control', 'no-cache')res.render('login');
});

当index.css发生改变再次请求时

终端输出的时间变化

服务端的时间跟last-modified的值是一致的

使用以上方式的协商缓存已经存在两个非常明显的漏洞。这两个漏洞都是基于文件是通过比较修改时间来判断是否更改而产生的。

1.因为是更具文件修改时间来判断的,所以,在文件内容本身不修改的情况下,依然有可能更新文件修改时间(比如修改文件名再改回来),这样,就有可能文件内容明明没有修改,但是缓存依然失效了。

2.当文件在极短时间内完成修改的时候(比如几百毫秒)。因为文件修改时间记录的最小单位是秒,所以,如果文件在几百毫秒内完成修改的话,文件修改时间不会改变,这样,即使文件内容修改了,依然不会 返回新的文件。

为了解决上述的这两个问题。从http1.1开始新增了一个头信息,ETag(Entity 实体标签)

Etag,If-None-Match

ETag就是将原先协商缓存的比较时间戳的形式修改成了比较文件指纹。

其实Etag,If-None-Match跟Last-Modified,If-Modified-Since大体一样,区别在于:

  • 后者是对比资源最后一次修改时间,来确定资源是否修改了
  • 前者是对比资源内容,来确定资源是否修改

那我们要怎么比对资源内容呢?我们只需要读取资源内容,转成hash值,前后进行比对就行了!

app.get('/login', function(req, res){// 设置 Expires 响应头// const time = new Date(Date.now() + 300000).toUTCString()// res.header('Expires', time)// const { mtime } = fs.statSync(path.join(__dirname, 'public/index.css')) // 读取最后修改时间// console.log(mtime.toUTCString(), '--------')// 响应头的last-modified字段// res.header('last-modified', mtime.toUTCString())// 设置ETagconst ifNoneMatch = req.header['if-none-match']const hash = crypto.createHash('md5')const fileBuf = fs.readFileSync(path.join(__dirname, 'public/index.css'))hash.update(fileBuf, 'utf8')const etag = `"${hash.digest('hex')}"`console.log(etag, '---etag----')// 对比hash值if (ifNoneMatch === etag) {res.status = 304} else {res.header('etag', etag)// ctx.body = fileBuffer}// 设置 Cache-Control 响应头res.header('Cache-Control', 'no-cache')res.render('login');
});

当资源发生改变时,状态码变成200,更新缓存

比如更改css样式

ETag也有缺点

  • ETag需要计算文件指纹这样意味着,服务端需要更多的计算开销。如果文件尺寸大,数量多,并且计算频繁,那么ETag的计算就会影响服务器的性能。显然,ETag在这样的场景下就不是很适合。
  • ETag有强验证和弱验证,所谓将强验证,ETag生成的哈希码深入到每个字节。哪怕文件中只有一个字节改变了,也会生成不同的哈希值,它可以保证文件内容绝对的不变。但是,强验证非常消耗计算量。ETag还有一个弱验证,弱验证是提取文件的部分属性来生成哈希值。因为不必精确到每个字节,所以他的整体速度会比强验证快,但是准确率不高。会降低协商缓存的有效性。

值得注意的一点是,不同于cache-control是expires的完全替代方案(说人话:能用cache-control就不要用expiress)。ETag并不是last-modified的完全替代方案。而是last-modified的补充方案(说人话:项目中到底是用ETag还是last-modified完全取决于业务场景,这两个没有谁更好谁更坏)。

disk cache & memory cache

磁盘缓存+内存缓存,这两种缓存不属于http缓存,而是本地缓存了~

我们直接打开掘金官网,点击network,类型选择all

可以看的很多请求,这里请求包括了静态资源+接口请求

这里我们能够看的很多请求的size中有很多是disk cache(磁盘缓存)

也有一些图片是memory cache(内存缓存)

这两者有什么区别呢?

disk cache: 磁盘缓存,很明显将内容存储在计算机硬盘中,很明显,这种缓存可以占用比较大的空间,但是由于是读取硬盘,所以速度低于内存

memory cache: 内存缓存,速度快,优先级高,但是大小受限于计算机的内存大小,很大的资源还是缓存到硬盘中

上面的浏览器缓存已经有三个大点了,那它们的优先级是什么样的呢?

缓存的获取顺序如下:

1.内存缓存

2.磁盘缓存

3.强缓存

4.协商缓存

如果勾选了Disable cache,那磁盘缓存都不存在了,之还有内存缓存

我还发现,勾选了Disable cache,就base64图片一定会在内存缓存中,其他图片则会发起请求;而不勾选了Disable cache,则大多数图片都在内存缓存中

CDN缓存

CDN缓存是一种服务端缓存,CDN服务商可以将源站上的资源缓到其各地的边缘服务器节点上。当用户访问该资源时,CDN再通过负载均衡将用户的请求调度到最近的缓存节点上,有效减少了链路回源,提高了资源访问效率及可用性,降低带宽消耗。

如果客户端没有命中缓存,那接下来就要发起一次网络请求,根据网络环境,一般大型站点都会配置CDN,CDN会找一个最合适的服务节点接管网络请求。CDN节点都会在本地缓存静态文件数据,一旦命中直接返回,不会穿透去请求应用服务器。并且CDN会通过在不同的网络,策略性地通过部署边缘服务器和应用大量的技术和算法,把用户的请求指定到最佳响应节点上。所以会减少非常多的网络开销和响应延迟。

如果没有部署CDN或者CDN没有命中,请求最终才会落入应用服务器,现在的http服务器都会添加一层反向代理,例如nginx,在这一层同样会添加缓存层,代表技术是squid,varnish,当然nginx作为http服务器而言也支持静态文件访问和本地缓存技术,当然也可以使用远程缓存,如redis,memcache,这里缓存的内容一般为静态文件或者由服务器已经生成好的动态页面,在返回用户之前缓存。

如果前面的缓存机制全部失效,请求才会落入真正的服务器节点。

总结

1.如果页面是协商缓存,如何获取页面最新内容?

协商缓存比较好办,那就刷新页面,不过需要勾选Disable cache,但是用户不知道打开控制台怎么办?

那就右击页面的刷新按钮,然后选择硬性重新加载,或者清空缓存并硬性重新加载,页面就获取到最新资源了

2.如果页面没有设置cache-control,那默认的缓存机制是什么样的?

默认是协商缓存,这也符合浏览器设计,缓存可以减少宽度流量,加快响应速度

3.如果项目重新部署还是没有更新,怎么办?

在确定项目已经部署成功

这样子,可以去问一下公司的运维同事,这个项目是否有CDN缓存

如果项目的域名做了CDN缓存,就需要刷新CDN目录,来解决缓存问题了,不然就只能等,等CDN策略失效,来请求最新的内容

向如下配置的缓存策略,只有过30天才会去真正服务器去请求最新内容

当然你可以测试一下是否为CDN缓存,在url后面拼接一个参数,就能够获取到最新资源了,比如有缓存的链接是https://baidu.com/abc

你可以在浏览器中输入https://baidu.com/abc&t=1234来判断一下,如果访问的是更改后的内容了,那就是原来的链接有CDN缓存导致没有刷新

当然特定场景,我们不能随意给链接后面添加参数,所以这也只适用于测试一下是否有CDN缓存

所以最好的解决办法还是需要让运维同事去刷新目录,这样就能快速解决CDN缓存问题。

参考链接

https://juejin.cn/post/7127194919235485733

https://juejin.cn/post/7177568033316012088

https://xiaolincoding.com/network/2_http/http_interview.html#http-%E7%BC%93%E5%AD%98%E6%8A%80%E6%9C%AF

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/106173.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【RuoYi移动端】uniApp导入和引用uView2.0插件

一、打开uiew官网 安装 | uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架uView UI,是 uni-app 生态最优秀的 UI 框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水https://uviewui.com/components/install.html 也可直…

基于Java+SpringBoot+Vue前后端分离在线考试与学习交流网页平台设计和实现

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

SpringSession

Spring Session 是 Spring 的项目之一。Spring Session 提供了一套创建和管理 Servlet HttpSession 的方案,默认采用外置的 Redis 来存储 Session 数据,以此来解决 Session 共享的 问题。(springsession储存session数据的方式有很多,我们常…

excel中两列数据生成折线图

WPS中excel的两列数据,第一列为x轴,第二列为y轴,生成折线图,并生成拟合函数。 1.选中两列数据,右击选择插入图表,选择XY(散点图),生成散点折线图 2.选中图中散点&#x…

SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka)

一、spring cloud简介 spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它运行环境简单,可以在开发人员的电脑上跑。另外说明spring cloud是基…

Web服务器基础 http协议

文章目录 1.Web基础1.1MIME1.2 URI 和 URL1.2.1定义1.2.2两者的区别 2.静态资源和动态资源2.1 静态资源2.2 动态资源 3.HTTP协议3.1HTTP协议简介3.2HTTP协议的版本及区别3.2.1http协议版本3.2.2http1.0和1.1的区别 3.3HTTP请求报文3.4HTTP请求访问的过程1、建立连接&#xff1a…

服务器CPU飚高排查

排查思路 当正在运行的Java服务导致服务器的CPU突然飙高时,我们该如何排查定位到哪个接口的哪行代码导致CPU飙高的问题呢?我主要提供两个方案: jstackarthas 准备工作 代码准备 现在需要准备一段可以让服务器CPU飙高的代码以及把代码部署…

Go framework-Kratos

目录 一、Go framework 1、Kratos 介绍 1.1、Kratos 框架开发依赖安装 2、初始化 Kratos 项目 3、使用 Protobuf 、生成 Go 代码 3.1、增加proto文件模板 3.2、修改proto文件模板 3.3、根据修改完的模板文件生成客户端代码 3.4、根据修改完的模板文件生成服务端代码 …

Windows平台Unity下播放RTSP或RTMP如何开启硬解码?

我们在做Windows平台Unity播放RTMP或RTSP的时候,遇到这样的问题,比如展会、安防监控等场景下,需要同时播放多路RTMP或RTSP流,这样对设备性能,提出来更高的要求。 虽然我们软解码,已经做的资源占有非常低了…

在外SSH远程连接macOS服务器

文章目录 前言1. macOS打开远程登录2. 局域网内测试ssh远程3. 公网ssh远程连接macOS3.1 macOS安装配置cpolar3.2 获取ssh隧道公网地址3.3 测试公网ssh远程连接macOS 4. 配置公网固定TCP地址4.1 保留一个固定TCP端口地址4.2 配置固定TCP端口地址 5. 使用固定TCP端口地址ssh远程 …

MySQL—MySQL的NULL值是怎么存放的

一、引言 1、MySQL数据存放在哪个文件? 创建一个数据库会产生三种格式的文件,分别是.opt格式、.frm格式、.ibd格式。 opt格式:用来存储当前数据库的默认字符集和字符校验规则。 frm格式:该文件是用来保存每个表的元数据信息的&…

ChatGPT⼊门到精通(1):ChatGPT 是什么

⼀、直观感受 1、公司 OpenAI(美国) 2、官⽅⽹站 3、登录ChatGPT ![在这里插入图片描述](https://img-blog.csdnimg.cn/26901096553a4ba0a5c88c49b2601e6a.png 填⼊帐号、密码,点击登录。登录成功,如下 3、和ChatGPT对话 开始…

Llama-2大模型本地部署研究与应用测试

最近在研究自然语言处理过程中,正好接触到到大模型,特别是在年初chatgpt引来的一大波AIGC热潮以来,一直都想着如何利用大模型帮助企业的各项业务工作,比如智能检索、方案设计、智能推荐、智能客服、代码设计等等,总得感…

四信5G智慧交通方案

5G是第五代移动通信技术的简称,是具有高速率低时延和大连接特点的新一代宽带移动通信技术,是实现智慧交通中的“车、路、人、环境”等交通要素互联互通的网络基础设施。相比以往的移动通信网络,5G网络以一种灵活部署的架构提供10Gbps以上的带…

Python中的API构建指南:在Flask中进行API开发

原文:Python中的API构建指南:在Flask中进行API开发 - 知乎 如何实现从一个软件与另一个软件的通信交互?就像我们的APP,如何实现微信支付、苹果支付? 其实,我们只需要一个API。 API(应用程序编…

4G模组EC20 网卡udhcpc获取IP但是没有设置IP

使能网卡: ifconfig usb0 up dhcp获取ip,虽然没有报error,但是很显然没有设置进配置 获取ip命令:udhcpc -i usb0 非正常现象: 正常现象: 解决方法: (1)rootfs 创建文件夹…

Qt应用开发(基础篇)——富文本浏览器 QTextBrowser

一、前言 QTextBrowser类继承于QTextEdit,是一个具有超文本导航的富文本浏览器。 框架类 QFramehttps://blog.csdn.net/u014491932/article/details/132188655 滚屏区域基类 QAbstractScrollAreahttps://blog.csdn.net/u014491932/article/details/132245486 文…

保姆级使用vmware安装Ubuntu-server版

保姆级VMware安装Ubuntu20服务器版 文章目录 保姆级VMware安装Ubuntu20服务器版前期准备一、安装vmware二、下载Ubuntu镜像 VMware安装Ubuntu201. 启动Workstation Pro或者Workstation Player,进入软件后新建一个虚拟机2. 进入引导界面选择默认的即可3. 点击下一步即可4. 选择操…

AIGC人工智能涉及三十六职业,看看有没有你的职业(二)

文章目录 如何生成IP盲盒 设计儿童节海报 制作商用矢量插画 设计徽章 图片融合 后缀参数 Stylize 风格化 赛博朋克头像 中国风瓷娃娃 生成线稿 制作时尚音乐唱片封面 T恤图案设计-告白气球 引领时尚潮流的服装设计之旅 独一无二的包包奇迹 手机壳设计探险 如何生…

Flink源码之Checkpoint执行流程

Checkpoint完整流程如上图所示: JobMaster的CheckpointCoordinator向所有SourceTask发送RPC触发一次CheckPointSourceTask向下游广播CheckpointBarrierSouceTask完成状态快照后向JobMaster发送快照结果非SouceTask在Barrier对齐后完成状态快照向JobMaster发送快照结…