HTTP缓存到底是什么

什么是缓存

缓存是一种保存资源副本并在下次请求时直接使用副本的技术。缓存包括HTTP缓存和浏览器缓存。下文将详细讲解HTTP缓存

缓存的作用

  • 直接从本地获取缓存资源,降低了服务器压力,提升了加载速度
  • 通过复用以前获取的资源,可以显著提高网站和应用程序的性能

什么是http缓存

HTTP缓存就是当浏览器第二次向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有"要请求资源"的副本,就直接从浏览器缓存中提取,不再向服务端发送请求获取数据。

HTTP缓存大致分为强缓存和协商缓存 这两类。这两种缓存策略都是服务端设置 HTTP的Header 来实现的。
强制缓存如果生效,不需要再和服务器发生交互,而协商缓存不管是否生效,都需要与服务端发生交互。

HTTP服务器常见响应返回状态码304,304代表告诉浏览器本地有缓存数据,可直接从本地获取,无需再发送请求向服务器获取

强缓存

直接从浏览器缓存的本地进行获取,不会去请求服务器。

当浏览器向服务器请求数据的时候,服务器会将数据和缓存的规则返回,在响应头的 header 中,有三个字段 ExpiresPragmaCache-Control共同决定。

Expires

Expires是HTTP1.0版本的属性,它的值是一个日期,是一个绝对时间,是当前返回数据缓存到期时间戳。当浏览器在进行请求的时候,系统时间会和expires时间做对比,如果系统时间超过了expires的值,表示浏览器缓存失效,会再向服务器端请求获取资源。

问题: 由于是系统时间做对比,如果手动改变电脑系统的时间,会有缓存有效期不准的问题,这就是HTTP1.0的问题,expires的优先级在三个header属性中最低的

Pragma

Pragma是http1.0版本的属性,它只有一个属性值,为no-cache,表示不使用强缓存,每次在向客户端(浏览器)提供响应数据时,缓存都要向服务器评估缓存响应的有效性。但目前基本不使用Pragma

Pragma和Cache-Control类似,但Pragma: no-cache可以应用到HTTP 1.0 和HTTP 1.1,而Cache-Control: no-cache只能应用于HTTP 1.1

cache-control

cache-control是HTTP 1.1中新增的属性,在请求头和响应头中都可以使用,常见的属性值有

属性值 属性值代表意思
public 表示缓存可以被任何对象(包括发送请求的客户端、中间代理、CDN缓存等)
private 表示用户只能被浏览器缓存,不能作为共享缓存,即代理服务器和CDN不能缓存比响应
no-cache 不使用强缓存,需要与服务器验证是否为最新资源
no-store 禁止使用缓存(包括协商缓存),每次都向服务器请求最新的资源
max-age 单位是秒,缓存存储的最大周期,超过这个周期被认为过期
must-revalidate 当页面过期时,去服务器进行获取

强缓存优先级

如果三者同时存在,则 Pragma优先级>cache-control优先级 > expires优先级

使用

js 复制代码
// 控制浏览器不要缓存:
// 由于历史原因,设置不读取缓存的时候三者都需要设置。

response.setDateHeader("Expires", -1);

response.setHeader("Pragma", "no-cache");

response.setHeader("Cache-control", "no-cache");

// 控制浏览器使用缓存:

response.setDateHeader("Expires", System.currentTimeMillis()+1000*60*60*24);     //24小时

response.setHeader("Cache-control", "max-age=60");    //60秒(优先级更高)

协商缓存

每次请求需要让服务器判断一下资源是否更新过,从而决定浏览器是否使用缓存,如果是,则返回 304,否则重新完整响应。

协商缓存表示在使用本地的缓存之前,会先向服务器发一个请求,与服务器协商当前浏览器的缓存是否已经过期了,如果没过期,那么就使用本地的资源,如果过期了就去请求最新资源。协商缓存主要是解决强缓存资源不能及时更新的问题

协商缓存主要通过两种方式实现: Last-ModifiedIfModified-SinceEtagIf-None-Match

Last-Modified 与 IfModified-Since

  • Last-Modified和if-Modified-Since的值都是GMT格林尼治格式的事件字符串,代表的是文件的最后修改时间

  • 在客户端第一次请求服务器时,服务器会读取这个文件的最后修改时间,然后设置Last-Modified参数到响应头,参数值就是文件最后修改的时间戳,将其返回并存储在客户端

  • 客户端再次请求服务器时,请求头会带上上一次响应头的Last-Modified的时间,并将其放到if-Modified-Since请求头属性中

  • 服务端收到此请求头发现有if-Modified-Since,则将这个参数与Last-Modified进行对比,如果时间一致,则服务器端的资源没有变化,自动返回HTTP状态码304(Not Changed.)状态码,内容为空,客户端接到之后,就直接把本地缓存文件显示到浏览器中

  • 如果时间不一致,则服务器端资源发生改变或者重启服务器,就返回HTTP状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中

Etag 与 If-None-Match

  • Etag和If-None-Match的值是一串hash码,代表的是一个资源的标识符

  • Etag是服务端为文件生成的一个唯一标识,资源的每一次变化都会导致Etag的变化,即当客户端第一次请求服务器时,服务器端会在响应头塞进Etag以及其计算出的字符串参数,将其返回给客户端

  • 客户端接收到Etag后,在第二次请求会带上If-None-Match的参数,再与被请求资源的唯一标识Etag进行对比,如果相同,则没有修改,响应返回304,浏览器直接从缓存中获取资源;反之,返回200,响应整个资源内容

协商缓存优先级

如果Etag和Last-Modified同时存在时,则 Etag优先级>Last-Modified优先级

强缓存和协商缓存的优先级

如果强缓存和协商缓存同时存在,如果强缓存还在生效期则强制缓存覆盖协商缓存,对比缓存不生效;如果强缓存不在有效期,协商缓存生效。则强缓存优先级 > 协商缓存优先级

总结

通过前文,我们了解到 HTTP 缓存主要分强制缓存和协商缓存。强制缓存由 Cache-Control(HTTP1.1),Exipres(HTTP1.0)控制。浏览器直接读本地缓存,不会再跟服务器端交互,状态码 200。协商缓存由 Last-ModifiedIfModified-SinceEtagIf-None-Match实现,每次请求需要让服务器判断一下资源是否更新过,从而决定浏览器是否使用缓存,如果是,则返回 304,否则重新完整响应,返回200。

相关推荐
加班是不可能的,除非双倍日工资14 分钟前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi1 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip1 小时前
vite和webpack打包结构控制
前端·javascript
excel2 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国2 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼2 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy2 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT2 小时前
promise & async await总结
前端
Jerry说前后端2 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天2 小时前
A12预装app
linux·服务器·前端