HTTP 缓存

139 阅读3分钟

一直以来觉得自己对http 缓存不是很了解,所以特此来记录一下(手动狗头)

HTTP 基础信息

http报文就是浏览器向服务器发送数据和浏览器接收来自服务器的返回数据 发送的数据分别称为请求报文, 返回的数据称为响应报文

报文主要是分为两个部分

一个是请求头 Header(cookie 和 缓存规则)

一个是请求体 Body 这里传输的主要的信息

http 缓存规则

为了方便理解, 将浏览器的缓存理解为一个小型的数据库, 浏览器第一次发送请求时, 因为缓存数据库没有数据, 所以需要请求服务器, 将返回的数据存入缓存数据库中

sequenceDiagram
客户端->>缓存数据库: 发送请求
缓存数据库-->>客户端: 暂无缓存数据
客户端-) 服务器: 发送请求
服务器--) 客户端: 返回响应报文
客户端->>缓存数据库: 保存数据

缓存的规则一般分为强缓存和协商缓存 基于已有缓存数据, 强缓存的流程图

sequenceDiagram
客户端->> 缓存数据: 发送请求
缓存数据-->>客户端: 数据未失效且返回数据

缓存数据失效

sequenceDiagram
客户端->>缓存数据库: 发送请求
缓存数据库-->>客户端: 存在缓存数据但是已经失效
客户端-) 服务器: 发送请求
服务器--) 客户端: 返回响应报文
客户端->>缓存数据库: 保存数据

基于已有的缓存数据,协商缓存流程图

sequenceDiagram
客户端->>缓存数据库: 获取缓存标识
缓存数据库-->>客户端: 返回缓存标识
客户端-) 服务器: 发送缓存标识验证数据是否失效
服务器--) 客户端: 通知未失效
客户端->>缓存数据库: 获取缓存数据

缓存数据失效

sequenceDiagram
客户端->>缓存数据库: 获取缓存标识
缓存数据库-->>客户端: 返回缓存标识
客户端-) 服务器: 发送缓存标识验证数据是否失效
服务器--) 客户端: 通知失效并返回数据
客户端->>缓存数据库: 将返回的数据存入缓存数据中

从流程图中可以看出, 强缓存如果未失效是不需要请求服务器的, 协商缓存无论怎样都需要和服务器交互, 还有一点的是强缓存的优先级大于协商缓存, 也就说如果这两个规则同时存在, 会优先执行强缓存

强缓存

从上文得知, 强缓存数据未失效是直接不请求服务器的, 所以我们如何来判断缓存数据的是否失效的呢? 一般强缓存的失效有两种判断, 一 :Expires为服务器到期时间, 另一个是Cache-Control,不过现在Expires针对于http1.0 有效并且服务器到期时间和客户端时间有一定的误差,所以强缓存一般用Cache-Control,

Cache-Control
Cache-Control一般都有以下属性

  1. private  服务器可以缓存
  2. public   服务器和代理服务器可以缓存
  3. max-age=xxx   失效的时间
  4. no-cache   使用协商缓存
  5. no-store   不使用缓存, 对于优化来说不可能不缓存,所以这个一般都不考虑

协商缓存

缓存标识一般都在request请求header 和 响应header 中 一般有两种方式

Last-Modified  /  If-Modified-Since
Last-Modified
请求服务器时, 返回数据的最后修改时间

image.png
If-Modified-Since

再次请求时,此属性告诉服务器上次请求的修改时间,如果服务器数据的修改时间大于此修改时间,则需要重新响应整个资源,返回状态码200。如果数据库修改的时间小于此修改时间,则返回状态304,通知浏览器直接取缓存数据即可。

image.png

Etag  /  If-None-Match(优先级高于Last-Modified  /  If-Modified-Since)

Etag

服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)

image.png

If-None-Match 当再次请求该资源时, 将从客户端传过来的标识符与服务器里拿到的标识符进行比对,如果标识符不一样,则返回响应的内容和状态码200,否则返回304.

总结

对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。对于比较缓存,将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存

浏览器第一次请求

image.png

再次请求时

image.png

本文转自彻底弄懂HTTP缓存机制及原理