HTTP权威指南:HTTP缓存机制与策略详解

Executive Summary

核心观点(金字塔原理)

结论先行: HTTP缓存通过存储响应副本减少网络传输,是提升Web性能的关键机制;通过新鲜度检测和再验证确保缓存一致性。

支撑论点:

  1. 缓存价值:减少冗余传输节省带宽、缓解网络瓶颈、降低服务器负载、减少距离时延
  2. 缓存机制:缓存命中/未命中判定、If-Modified-Since再验证、304 Not Modified优化
  3. 控制策略:Cache-Control指令(no-store/no-cache/max-age/must-revalidate)精细控制缓存行为

SWOT 分析

| 维度 | 分析 | |——|——| | S 优势 | 显著降低响应时延;减少带宽消耗和网络费用;缓解源服务器压力防止过载 | | W 劣势 | 缓存不一致风险;私有数据误缓存的安全隐患;缓存失效策略复杂难以调优 | | O 机会 | 代理缓存层次结构支持大规模部署;ETag精确验证;客户端可主动控制缓存行为 | | T 威胁 | 动态内容难以缓存;缓存投毒攻击风险;CDN配置错误导致数据泄露 |

适用场景

  • 优化网站性能时设计缓存策略
  • 配置CDN或代理缓存规则
  • 排查缓存不一致或缓存穿透问题

缓存

使用缓存的优点

  1. 减少冗余的数据传输,节省了你的网络费用
  2. 缓解了网络瓶颈的问题,不需要更多的带宽就能够更快地加载页面
  3. 降低了对原始服务器的要求,服务器可以更快地响应,避免过载的出现
  4. 降低了距离时延,因为从较远的地方加载页面会更慢一些
冗余的数据传输

服务器多次传输同一份文档,每次传输给一个客户端,相同的字节在网络中一遍遍地传输,造成冗余,缓存可以很好解决这个问题。

带宽瓶颈

缓存可以缓解网络带宽瓶颈问题。

瞬间拥塞

缓存在破坏瞬间拥塞时显得非常重要,比如突发事件,使很多人几乎同时访问一个Web文档时,就会出现瞬间拥塞,由此造成Web服务器负载过高甚至崩溃。

距离时延

即便带宽不是问题,距离也可能是问题的原因,没太网络路由器都会增加因特网流量的时延,即使没有太多路由器,光速本身也会造成显著的时延。

命中和未命中的

可以用已有副本为某些到达缓存的请求提供服务,被称为缓存命中,亦或请求的资源在缓存服务器上不存在,而将请求转发给原始服务器被称为缓存未命中

  • 再验证以保持缓存的”新鲜度”,在缓存服务器向源服务器发送请求的首部加上If-Modified-Since首部,告诉源服务器只有在缓存了对象的副本之后,又对其进行了修改的情况下,才发送此对象。
  1. 再验证命中(如果服务器对象未被修改,服务器想客户端发送一个小的HTTP304Not Modified响应)
  2. 再验证未命中(如果服务器对象与已缓存副本不同,则向客户端发送一条普通的,带有完整内容的HTTP 200 OK响应)
  3. 对象被删除(如果服务器对象已经被删除了,服务器回送一个404 Not Found响应,缓存也会将其副本删除)
  • 命中率
  • 字节命中率
  • 区分命中和未命中的情况(根据Date首部,若响应日期比较早,则为缓存响应)
缓存的拓扑结构
  • 私有缓存(比如浏览器缓存)
  • 公有代理缓存或者称为代理缓存
  • 代理缓存的层次结构
  • 网状缓存、内容路由以及对等缓存
缓存的处理步骤

对一条HTTP GET报文的基本缓存处理过程包括7个步骤:

  1. 接收-缓存从网络中读取抵达的请求报文。
  2. 解析-缓存对报文进行解析,提取出URL和各种首部。
  3. 查询-缓存查看是否本地有副本可用,如果没有,就获取一份并缓存本地
  4. 新鲜度检测-缓存查看已缓存副本是否足够新鲜,如果不是,就询问源服务器是否有任何更新。
  5. 创建响应-缓存会用新的首部和已缓存的主体来构建一条响应报文
  6. 发送-缓存通过网络将响应发回给客户端
  7. 日志-缓存可选地创建一个日志文件条目来描述这个事务
  • 文档过期设置(Cache-Control: max-age=3600指定最大使用期限以秒为单位; Expires: Fri, 05 Jul 2002, 05:00:00 GMT指定一个绝对的过期日期)
  • 服务器再验证
  • 在请求报文中添加用条件方法进行再验证
  1. If-Modified-Since:
  2. If-None-Match:
控制缓存的能力
  • 服务器可以通过HTTP定义的几种方式来指定在文档过期之前可以将其缓存多长时间,按照优先级递减的顺序。服务器可以:
  1. 附加一个Cache-Control: no-store 首部到响应中去;
  2. 附加一个Cache-Control: no-cache 首部到响应中去;
  3. 附加一个Cache-Control: must-revalidate 首部到响应中去;
  4. 附加一个Cache-Control: max-age 首部到响应中去;
  5. 附加一个Expires 日期首部到响应中去;
  6. 不附加过期信息,让缓存确定自己的过期日期;
  • 客户端的新鲜度限制
指令 目的
Cache-Control: max-fresh = <s> 至少在未来<s>秒内文档要保持新鲜。
Cache-Control: max-age = <s> 缓存无法返回缓存时间长于<s>秒的文档
Cache-Control: no-cache 除非资源进行再验证,否则这个客户端不会接受已缓存的资源
Cache-Control: no-store 缓存应尽快从存储器中删除文档的所有痕迹,因为其中可能会包含敏感信息
Cache-Control: only-if-cached 只有当缓存中有副本存在时,客户端才会获取一份副本