第7章 缓存

建立缓存命中、拓扑、处理步骤、新鲜度、再验证、缓存控制、年龄算法和广告计量

第7章 缓存

“第7章 缓存”锁定David Gourley、Brian Totty、Marjorie Sayer、Sailu Reddy、Anshu Aggarwal著,陈涓、赵振平译《HTTP权威指南》,人民邮电出版社,2012年,ISBN 9787115281487;英文原版HTTP: The Definitive Guide,O'Reilly Media,2002年9月,656页,ISBN 1565925092。O'Reilly官方页面确认英文首版的5个正文部分、21章和8个附录;中文版完整印刷目录另含“第六部分 附录”和索引。忠实度分母共586个部分、章、编号节/小节、附录与索引节点。

“第7章 缓存”未取得未获授权的完整中文正文;课程以 O’Reilly 官方在线版章级导览 界定首版范围,中文解释、报文、实验和练习均为独立教学重写。现代语义仅以 RFC 9110RFC 9111RFC 9112 核对差异。

学习目标

  • 能解释“第7章 缓存”的全部正式节点及其HTTP事务位置。
  • 能绘制请求、响应、TCP连接、中间实体和资源状态。
  • 能设计单变量实验,验证“缓存响应能证明副本键、当前年龄、新鲜寿命、验证器、Vary维度和再验证结果”。
  • 能写出含首版边界、原始报文、故障、恢复和复核人的证据包。

从一条可证伪的HTTP事务开始

先预测:把no-cache当作绝不存储或忽略Age/Vary会返回错误变体和陈旧内容。把预测写成“URL/资源、连接、请求报文、中间实体、响应报文、身份与编码”六行,再运行客户端、代理或服务器。结果不同先定位首个字节或状态偏差。

本页主问题是:建立缓存命中、拓扑、处理步骤、新鲜度、再验证、缓存控制、年龄算法和广告计量。每条消息要注明发送者、接收者、HTTP版本、连接复用、逐跳/端到端首部、主体边界与历史协议状态。

验收不变量是:缓存响应能证明副本键、当前年龄、新鲜寿命、验证器、Vary维度和再验证结果。最终页面正常、状态码200或TLS通道建立都只是局部事实,不能单独证明资源身份、缓存变体、代理转发与证书身份全部正确。

核心词汇与首版边界

这些词汇固定在2002年英文首版和2012年中译本语境。在“第7章 缓存”中,HTTP/2、HTTP/3、OAuth、JWT、SameSite、HSTS和现代CDN行为只作独立比较,不得替换HTTP-NG、Digest、WebDAV、WPAD等首版节点。

核心机制深读

先从缓存命中画出事务

建立缓存命中、拓扑、处理步骤、新鲜度、再验证、缓存控制、年龄算法和广告计量。先固定资源身份和请求目标,再标出客户端、中间实体与源服务器,任何优化或安全结论都不能跳过原始报文。

动手试:先手写预期请求与响应,再抓取正常事务和一个单变量故障事务。标出首个不同字节或状态,不用最终页面猜根因。

区分缓存命中与新鲜度

缓存命中和新鲜度可能在同一事务中协作,但责任、状态位置和失败语义不同。对比正常请求、单个首部变化和单个连接故障,定位首个偏差。

动手试:先手写预期请求与响应,再抓取正常事务和一个单变量故障事务。标出首个不同字节或状态,不用最终页面猜根因。

让验证器经过真实中间实体

代理、缓存、网关或隧道会读取、添加、删除或转发不同首部。逐跳记录Via、Connection列出的字段、缓存决策和认证边界。

动手试:先手写预期请求与响应,再抓取正常事务和一个单变量故障事务。标出首个不同字节或状态,不用最终页面猜根因。

验证当前年龄的历史语境

原书写于2002年,以HTTP/1.0、HTTP/1.1、SSL/TLS早期版本和当时Web基础设施为背景。现代实现可做对照,但不能冒充原书节点。

动手试:先手写预期请求与响应,再抓取正常事务和一个单变量故障事务。标出首个不同字节或状态,不用最终页面猜根因。

用再验证关闭证据门

缓存响应能证明副本键、当前年龄、新鲜寿命、验证器、Vary维度和再验证结果。证据至少包含原始请求/响应、TCP时间线、中间状态、失败注入、恢复动作和第三方复核。

动手试:先手写预期请求与响应,再抓取正常事务和一个单变量故障事务。标出首个不同字节或状态,不用最终页面猜根因。

首版机制逐项深读

第7章 缓存

验证“第7章 缓存”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.1 冗余的数据传输

“7.1 冗余的数据传输”在本章用于回答“建立缓存命中、拓扑、处理步骤、新鲜度、再验证、缓存控制、年龄算法和广告计量”。学习时必须把这个名称落到具体报文、连接、中间状态或历史规范,并说明它改变了哪项可观察结果。

7.2 带宽瓶颈

“7.2 带宽瓶颈”把 HTTP 等待拆成 DNS、建连、请求发送、服务器处理和响应传输;连接复用影响握手次数,但不能改变报文边界与应用语义。

7.3 瞬间拥塞

诊断“7.3 瞬间拥塞”先确定哪一端关闭、是否仍有未确认字节以及方法是否幂等;页面最终成功不能证明中间没有重复请求。

7.4 距离时延

评估“7.4 距离时延”要同时记录 TCP 四元组、分段与确认时间线和 HTTP 消息边界,避免把网络等待误判成服务器计算。

7.5 命中和未命中的

“7.5 命中和未命中的”由缓存键、当前年龄、新鲜寿命、Vary 维度和验证器共同决定;命中不等于新鲜,过期对象也可能通过条件请求复用。

7.5.1 再验证

“7.5.1 再验证”的故障常来自错误变体键、过期算法或共享与私有策略混用;证据包必须包含缓存日志和源站条件请求。

7.5.2 命中率

“7.5.2 命中率”的故障常来自错误变体键、过期算法或共享与私有策略混用;证据包必须包含缓存日志和源站条件请求。

7.5.3 字节命中率

分析“7.5.3 字节命中率”先计算校正年龄与新鲜寿命,再检查 Vary、ETag 或 Last-Modified 和请求指令;是否联系源站不是唯一证据。

7.5.4 区分命中和未命中的情况

“7.5.4 区分命中和未命中的情况”由缓存键、当前年龄、新鲜寿命、Vary 维度和验证器共同决定;命中不等于新鲜,过期对象也可能通过条件请求复用。

7.6 缓存的拓扑结构

分析“7.6 缓存的拓扑结构”先计算校正年龄与新鲜寿命,再检查 Vary、ETag 或 Last-Modified 和请求指令;是否联系源站不是唯一证据。

7.6.1 私有缓存

“7.6.1 私有缓存”的故障常来自错误变体键、过期算法或共享与私有策略混用;证据包必须包含缓存日志和源站条件请求。

7.6.2 公有代理缓存

“7.6.2 公有代理缓存”描述中间实体行为:它可能终止一侧连接、改写逐跳字段或转换协议,因此必须分别记录两侧报文和下一跳选择。

7.6.3 代理缓存的层次结构

“7.6.3 代理缓存的层次结构”的实验固定客户端与源站,只插入或移除一个中间节点,再比较两侧原始报文、认证边界和错误归属。

7.6.4 网状缓存、内容路由以及对等缓存

验证“7.6.4 网状缓存、内容路由以及对等缓存”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.7 缓存的处理步骤

验证“7.7 缓存的处理步骤”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.7.1 第一步——接收

“7.7.1 第一步——接收”的失败应归到接收、解析、映射、授权、执行或发送中的首个异常阶段;后续 500 响应只是结果,不是根因。

7.7.2 第二步——解析

“7.7.2 第二步——解析”位于服务器处理流水线:接收连接后解析请求、映射资源、执行访问控制、构造响应并记录日志;每一步都应留下可归责的输入与输出。

7.7.3 第三步——查找

验证“7.7.3 第三步——查找”固定 URL 与身份,只改变一项映射或权限配置,比较服务器选择的资源、状态码和日志责任字段。

7.7.4 第四步——新鲜度检测

“7.7.4 第四步——新鲜度检测”的故障常来自错误变体键、过期算法或共享与私有策略混用;证据包必须包含缓存日志和源站条件请求。

7.7.5 第五步——创建响应

验证“7.7.5 第五步——创建响应”固定 URL 与身份,只改变一项映射或权限配置,比较服务器选择的资源、状态码和日志责任字段。

7.7.6 第六步——发送

“7.7.6 第六步——发送”位于服务器处理流水线:接收连接后解析请求、映射资源、执行访问控制、构造响应并记录日志;每一步都应留下可归责的输入与输出。

7.7.7 第七步——日志

定位“7.7.7 第七步——日志”要用同一关联号串起连接、解析结果、资源映射、权限判定、响应元数据与访问日志,不能只观察浏览器页面。

7.7.8 缓存处理流程图

分析“7.7.8 缓存处理流程图”先计算校正年龄与新鲜寿命,再检查 Vary、ETag 或 Last-Modified 和请求指令;是否联系源站不是唯一证据。

7.8 保持副本的新鲜

验证“7.8 保持副本的新鲜”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.8.1 文档过期

“7.8.1 文档过期”由缓存键、当前年龄、新鲜寿命、Vary 维度和验证器共同决定;命中不等于新鲜,过期对象也可能通过条件请求复用。

7.8.2 过期日期和使用期

分析“7.8.2 过期日期和使用期”先计算校正年龄与新鲜寿命,再检查 Vary、ETag 或 Last-Modified 和请求指令;是否联系源站不是唯一证据。

7.8.3 服务器再验证

验证“7.8.3 服务器再验证”固定 URL 与身份,只改变一项映射或权限配置,比较服务器选择的资源、状态码和日志责任字段。

7.8.4 用条件方法进行再验证

分析“7.8.4 用条件方法进行再验证”要保留起始行、全部首部与实体边界;把解析对象重新打印,可能丢掉重复字段、空白和线路顺序证据。

7.8.5 if-modified-since:date 再验证

“7.8.5 if-modified-since:date 再验证”按修改日期验证缓存表示;时间粒度和时钟差会造成歧义,资源有可靠实体标签时通常更精确。

7.8.6 if-none-match:实体标签再验证

“7.8.6 if-none-match:实体标签再验证”让客户端携带已有表示的实体标签;标签匹配时服务器可返回 304,强验证器要求逐字节等价,弱验证器只保证语义等价。

7.8.7 强弱验证器

验证“7.8.7 强弱验证器”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.8.8 什么时候应该使用实体标签和最近修改日期

“7.8.8 什么时候应该使用实体标签和最近修改日期”让客户端携带已有表示的实体标签;标签匹配时服务器可返回 304,强验证器要求逐字节等价,弱验证器只保证语义等价。

7.9 控制缓存的能力

验证“7.9 控制缓存的能力”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.9.1 no-store 与no-cache 响应首部

“7.9.1 no-store 与no-cache 响应首部”中 no-store 禁止保存响应,no-cache 允许保存但复用前必须验证;二者都不是简单的“立即删除浏览器缓存”。

7.9.2 max-age 响应首部

“7.9.2 max-age 响应首部”给出响应自生成起可视为新鲜的秒数;当前年龄达到寿命后需验证或回源,不能从下载时刻重新计时。

7.9.3 expires 响应首部

“7.9.3 expires 响应首部”用绝对日期声明过期时间,依赖发送端与接收端时钟;相对的 max-age 通常更不易受时钟偏差影响。

7.9.4 must-revalidate 响应首部

“7.9.4 must-revalidate 响应首部”要求过期响应在复用前成功验证;断网时也不能随意提供陈旧副本,除非其他明确规则允许。

7.9.5 试探性过期

“7.9.5 试探性过期”在缺少显式寿命时依据 Last-Modified 等历史信息估计新鲜期;这是有上限的启发式,不应伪装成源站承诺。

7.9.6 客户端的新鲜度限制

验证“7.9.6 客户端的新鲜度限制”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.9.7 注意事项

“7.9.7 注意事项”在本章用于回答“建立缓存命中、拓扑、处理步骤、新鲜度、再验证、缓存控制、年龄算法和广告计量”。学习时必须把这个名称落到具体报文、连接、中间状态或历史规范,并说明它改变了哪项可观察结果。

7.10 设置缓存控制

验证“7.10 设置缓存控制”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.10.1 控制apache 的http 首部

“7.10.1 控制apache 的http 首部”由发送者意图与接收者结果共同决定;状态成功并不能证明方法安全、幂等或表示完整。

7.10.2 通过http-equiv 控制html 缓存

“7.10.2 通过http-equiv 控制html 缓存”的故障常来自错误变体键、过期算法或共享与私有策略混用;证据包必须包含缓存日志和源站条件请求。

7.11 详细算法

“7.11 详细算法”在本章用于回答“建立缓存命中、拓扑、处理步骤、新鲜度、再验证、缓存控制、年龄算法和广告计量”。学习时必须把这个名称落到具体报文、连接、中间状态或历史规范,并说明它改变了哪项可观察结果。

7.11.1 使用期和新鲜生存期

“7.11.1 使用期和新鲜生存期”优先采用 s-maxage/max-age,其次 Expires,最后才使用启发式;共享缓存与私有缓存的指令优先级不同。

7.11.2 使用期的计算

“7.11.2 使用期的计算”合并 Date、Age、请求/响应时间与驻留时间,得到校正后的当前年龄;只看单个 Age 值会漏掉传输和本地驻留。

7.11.3 完整的使用期计算算法

“7.11.3 完整的使用期计算算法”合并 Date、Age、请求/响应时间与驻留时间,得到校正后的当前年龄;只看单个 Age 值会漏掉传输和本地驻留。

7.11.4 新鲜生存期计算

“7.11.4 新鲜生存期计算”优先采用 s-maxage/max-age,其次 Expires,最后才使用启发式;共享缓存与私有缓存的指令优先级不同。

7.11.5 完整的服务器——新鲜度算法

验证“7.11.5 完整的服务器——新鲜度算法”固定 URL 与身份,只改变一项映射或权限配置,比较服务器选择的资源、状态码和日志责任字段。

7.12 缓存和广告

“7.12 缓存和广告”由缓存键、当前年龄、新鲜寿命、Vary 维度和验证器共同决定;命中不等于新鲜,过期对象也可能通过条件请求复用。

7.12.1 发布广告者的两难处境

“7.12.1 发布广告者的两难处境”把请求路由到具体站点与版本:Host/地址决定虚拟主机,权限与写入协议控制发布,副本和分发节点必须保持资源身份与版本一致。

7.12.2 发布者的响应

“7.12.2 发布者的响应”把请求路由到具体站点与版本:Host/地址决定虚拟主机,权限与写入协议控制发布,副本和分发节点必须保持资源身份与版本一致。

7.12.3 日志迁移

定位“7.12.3 日志迁移”要用同一关联号串起连接、解析结果、资源映射、权限判定、响应元数据与访问日志,不能只观察浏览器页面。

7.12.4 命中计数和使用限制

验证“7.12.4 命中计数和使用限制”固定响应字节与缓存键,只改变 Age、寿命或验证器中的一个量,观察新鲜命中、304 再验证和完整回源。

7.13 更多信息

“7.13 更多信息”是原书的延伸资料入口,不增加新的协议结论;使用时必须记录资料版本、适用的 HTTP 年代和与本章结论的对应关系。

分步1 / 3

复原原始HTTP事务

固定URL、资源、连接与版本,写出请求行、首部、主体、响应和所有中间实体。

HTTP/1.1 message laboratory

第7章 缓存

建立缓存命中、拓扑、处理步骤、新鲜度、再验证、缓存控制、年龄算法和广告计量

请求方法
GET /resource?chapter=%E7%AC%AC7%E7%AB%A0%20%E7%BC%93%E5%AD%98 HTTP/1.1
Host: example.test
Connection: keep-alive

解析边界:首部空行结束请求

章内坐标:第7章 缓存、7.1 冗余的数据传输、7.2 带宽瓶颈、7.3 瞬间拥塞、7.4 距离时延、7.5 命中和未命中的、7.5.1 再验证、7.5.2 命中率

可复现实验记录

GET /resource HTTP/1.1
Host: example.test
Connection: keep-alive
Accept: */*
HTTP/1.1 200 OK
Date: Tue, 01 Jan 2002 00:00:00 GMT
Content-Type: text/plain
Content-Length: 5
 
hello
evidence = request_bytes + response_bytes + tcp_timeline + intermediary_state + recovery

动手试:保存一次正常请求、一次缓存或连接边界和一次单变量故障。记录客户端、代理、缓存、网关与源服务器看到的原始报文,以及统一时间戳和恢复动作。

独立证据门

最小证据包包含:首版节点、URL、原始请求/响应、连接时间线、代理与缓存决策、身份和编码、单变量故障、恢复、偏差、责任人与复核人。

练习

练习

问题 1:为什么“第7章 缓存”必须固定2002年首版?

问题 2:怎样构造“把no-cache当作绝不存储或忽略Age/Vary会返回错误变体和陈旧内容”的最小反例?

问题 3:何时可以认为本页完成独立交接?

本章回顾

“第7章 缓存”的核心是建立缓存命中、拓扑、处理步骤、新鲜度、再验证、缓存控制、年龄算法和广告计量。真正掌握不是记首部名,而是能用原始报文、连接和中间状态证明资源如何被定位、传输、缓存、保护与交付。

名词解释

本章出现的专业名词,用大白话再讲一遍。

缓存命中

请求由已有缓存副本满足而无需完整获取源响应的结果。掌握标准是能在原始HTTP报文、中间状态或历史规范中定位,并构造最小失败反例。

新鲜度

缓存副本无需联系源服务器即可复用的有效状态。掌握标准是能在原始HTTP报文、中间状态或历史规范中定位,并构造最小失败反例。

验证器

用于条件请求判断资源实例是否变化的ETag或日期标识。掌握标准是能在原始HTTP报文、中间状态或历史规范中定位,并构造最小失败反例。

当前年龄

响应自源生成以来按规范计算的累计时间。掌握标准是能在原始HTTP报文、中间状态或历史规范中定位,并构造最小失败反例。

再验证

缓存向源服务器用条件请求确认副本可否继续使用的过程。掌握标准是能在原始HTTP报文、中间状态或历史规范中定位,并构造最小失败反例。

← 上一页:第6章 代理 · 下一页:第8章 集成点:网关、隧道及中继 →

讨论

评论区加载中…