http 缓存机制

http 作为前端的必备知识点之一, 是每个前端开发者都需要掌握的, 基于近期的学习, 对 http 中缓存部分的知识进行一下梳理。不对之处,还忘评论区斧正, 多谢啦 ��~
前言

http 是基于 TCP 协议进行传输的一种文本传输协议, 用来与服务端之间进行交互, 可以理解为 浏览器向服务端发送一个携带请求报文的请求,服务端读取请求后响应浏览器并回应一个响应报文。

报文主要包含两部分
1. 包含属性的首部(header) => 附加信息(cookie,缓存信息等)与缓存相关的规则信息,均包含在header中
2. 包含数据的主体部分(body) => HTTP 请求真正想要传输的部分

以下是常见的请求头信息:

Accept: text/html,image/*                                      #浏览器可以接收的类型
Accept-Charset: ISO-8859-1                                     #浏览器可以接收的编码类型
Accept-Encoding: gzip,compress                                 #浏览器可以接收压缩编码类型
Accept-Language: en-us,zh-cn                                   #浏览器可以接收的语言和国家类型
Host: www.lks.cn:80                                            #浏览器请求的主机和端口
If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT               #某个页面缓存时间
Referer: http://www.lks.cn/index.html                          #请求来自于哪个页面
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5)    #浏览器相关信息
Cookie:                                                        #浏览器暂存服务器发送的信息
Connection: close1.0/Keep-Alive1.1                             #HTTP请求的版本的特点
Date: Tue, 11 Jul 2000 18:23:51GMT                             #请求网站的时间
Allow:GET                                                      #请求的方法 GET 常见的还有POST
Keep-Alive:5                                                   #连接的时间;5
Connection:keep-alive                                          #是否是长连接
Cache-Control:max-age=300                                      #缓存的最长时间 300s
缓存的作用
  1. 可以减少了冗余的数据传输,节省了网费。
  2. 可以减少了服务器的负担, 大大提高了网站的性能
  3. 加快了客户端加载网页的速度
http 缓存规则

这里写图片描述
为了方便理解, 可以认为浏览器有一个存档缓存数据的数据库。
当浏览器第一次向服务端发起请求时, 缓存数据库中没有缓存, 需要向服务端发送请求, 服务端接收到响应返回数据, 缓存数据库中会存储一份。

http 缓存规则有很多种, 根据是否需要向服务端发送请求来分类,可以大致分为两类 强制缓存 和 对比缓存,两类缓存规则可以同时存在, 强制缓存优先级高于对比缓存。
如果强制缓存规则生效, 就不在与服务端发生交互, 直接使用缓存, 不在执行对比缓存规则。

强制缓存

这里写图片描述
从图中可以看出强制缓存是 在缓存数据还没失效的情况下直接使用缓存中的数据, 不需要向服务端发送请求, 那么如何判断缓存中的数据是否失效呢?
上面有提及与缓存相关的规则信息,均包含在 Http 协议的 header中, 对于强制缓存来说可以通过 header 中两个字段来判断缓存是否失效, 分别是 Exprise 和 Cache-Control

第一次请求后浏览器会将文件缓存到缓存数据库中,第二次请求时浏览器会先检查缓存数据库中是否含有该文件,如果有并且还没到 缓存设置的失效时间,即文件还没有过期,那么此时浏览器将直接从缓存数据库中读取文件,而不再发送请求

这里写图片描述

Exprise: 服务端返回的到期时间, 即下一次请求时, 请求时间小于服务端返回的到期时间, 直接使用缓存数据
不过 Expires 是 HTTP 1.0 的东西, 现在浏览器默认均使用 HTTP 1.1 , 所以基本可以忽略这个字段
另一个问题是,到期时间是由服务端生成的,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。
所以 Http 1.1 的版本,使用 Cache-Control 替代

Cache-Control: 与 Expires 的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务端读取数据,如果同时设置的话,其优先级高于 Expires。

Cache-Control  常见的取值有 privatepublic、no-cachemax-age,no-store,默认为 privateprivate:             客户端可以缓存
public:              客户端和代理服务器都可缓存
max-age=30:          缓存的内容将在 30 秒后失效
no-cache:            需要使用对比缓存来验证缓存数据,强制向源服务器再次验证
no-store:            所有内容都不会缓存,强制缓存,对比缓存都不会触发

上图中的
Cache-Control 指定了 max-age=10, 10s 内浏览器读取数据的时候都会走缓存, 而过了 10s 之后在读取数据时, 需向服务器发送请求

对比缓存

这里写图片描述

对比缓存,顾名思义,需要进行比较判断是否可以使用缓存。其对比的过程是在服务端进行的, 因此不管是否读取缓存的数据都需要与服务端进行交互。
从途中可以看出,浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。
再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回 304 状态码,通知客户端比较成功,可以使用缓存数据, 反之如果不成功,服务端会返回新的内容与标识。

对于对比缓存来说,缓存标识的传递是我们着重需要理解的,它在请求 header 和响应 header 间进行传递,
一共分为两种标识传, 下面会分别介绍

If-Modified-Since 与 Last-Modified

Last-modified: 服务端响应时会带上此字段告知浏览器资源的最后修改时间

If-Modified-Since: 当资源过期时(使用 Cache-Control 标识的 max-age), 发现资源具有 Last-Modified 声明, 则再次向服务端发送请求并带上 If-Modified-Since,
服务端收到请求后发现 header 中有 If-Modified-Since 字段, 则与被请求当资源的最后修改时间进行对比。 若最后修改时间较新, 说明资源被改动过, 则响应最新的资源内容并返回 200 状态码
若最后修改时间和 If-Modified-Since 一样, 说明资源没有被修改, 则响应 304 告知 浏览器可以继续使用缓存中的文件。
这里写图片描述

If-Modified-Since 与 Last-Modified 最后修改时间存在的问题:
  1. 某些服务器不能精确得到文件的最后修改时间, 这样就无法通过最后修改时间来判断文件是否更新了。
  2. Last-Modified 只能精确到秒,某些文件的修改非常频繁,在秒以下的时间内进行修改, 就无法判断文件是否更新。
  3. 通常会有一些文件的最后修改时间改变了,但是内容并未改变。 次时我们并不希望客户端认为这个文件修改了。
  4. 如果同样的一个文件位于多个 CDN 服务器上的时候内容虽然一样,但修改时间不一样。
ETag 与 If-None-Match

If-None-Match: 服务器客户段缓存数据的唯一标识
Etag:是服务端根据实体内容生成的一段 hash 字符串, 可以标识资源的状态。 当资源发生改变时, ETag 也随之发生变化,然后通过响应头带到浏览器中。

客户端判断缓存是否可用, 需要先获取响应 header 中 ETag 的值, 然后请求的时候在 header 中通过 If-None-Match 发送到请求到服务端, 询问服务端缓存是否生效。
服务端收到请求后, 取出 If-None-Match 的值 与 请求文件的 hash 字符串进行比较, 如果相等说明文件未更改过, 服务端发出 304 的 code 给到浏览器告知缓存可以使用,
如果不相等 服务端将最新修改后的文件发送给浏览器, 并通过响应头设置 ETag 字段。

结尾

最后我们在通过两张图回顾以下请求缓存的过程

第一次请求
这里写图片描述

第二次请求
这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值