摘要
- RFC 2187 中的 parent、sibling 和 direct retrieval 是不同的操作权限与转发路径。sibling 可在确认 HIT 时供取对象,但 MISS 不能由 sibling 继续解析;parent 则可以在 HIT 或 MISS 后承担继续访问的 transit 角色,源站直取仍是独立选择。
- ICP 查询与响应只提供某一时刻、某一邻居、某一 URL 或对象状态的局部提示。邻居关系、HIT、RTT、权重、多播成员资格或一次成功抓取,都不能自动扩展为互惠授权、最低成本、端到端新鲜度、身份认证、内容安全、未来容量、策略对称或商业结果。
层级不是距离图,而是权限与转发规则
RFC 2187 对 Web cache hierarchy 的定义从 parent 和 sibling 两类关系出发。它把 parent 描述为层级中的“上一层”,sibling 则处在“同一层”;但随后立刻用请求如何流动来解释这些词,而不是用公里数、自治系统跳数或物理拓扑来解释。真正决定角色差异的,是 MISS 之后还能不能继续请求。
在这套模型里,本地缓存遇到自己没有的对象时,可以通过 ICP 询问邻居。若某个邻居给出 HIT,本地缓存可以从 parent 或 sibling 取回该对象。若所有邻居都 MISS,则下一步只能选择 parent,或者绕过层级直接访问 origin server。RFC 2187 的图 1 把三条路径分得很清楚:sibling 只解决 HITS;parent 可以解决 HITS AND MISSES;DIRECT RETRIEVALS 则从本地缓存指向互联网和源站。这里的“层级”首先是在回答“谁可以在什么条件下替谁继续向上游取得对象”,而不是回答“谁在地理上离谁最近”。
这一区别也解释了为什么 sibling 不等同于“同城缓存”,parent 也不等同于“远端上游”。RFC 2187 甚至允许同一个邻居对一类请求被当作 sibling,对另一类请求被当作 parent;还允许按 DNS 域等条件限制某个邻居的适用范围。角色因此是一种请求相关、策略相关的关系。只看节点标签,无法推出所有流量都服从同一关系,更无法推出双方对这段关系有对称理解。
更关键的是,这种关系不是由 ICP 报文本身声明的。RFC 2187 明确指出,ICP 请求或响应里没有字段表示两个 cache 是 parent 还是 sibling。一个 sibling 能回答 HIT 或 MISS,却不能在报文里表达“你可以从我这里继续取 MISS”或“你不可以”。发起查询的一侧必须把收到的 HIT/MISS 与自己的本地配置结合,才能避免错误地通过 sibling 解析 MISS;被查询的一侧则可以用访问控制间接约束关系。也就是说,协议提供状态信号,关系的含义由部署配置施加。
这正是“操作关系”比“物理距离”更准确的原因。即使一个 parent 在网络上更远,只要它被配置为可承担 transit,它仍然是 parent;即使一个 sibling 往返时延更小,只要双方的访问控制不允许它处理 MISS,它就不是后备上游。位置可以影响性能,却不定义授权。
HIT 证明什么,又没有证明什么
ICP 最容易产生过度解释的信号是 HIT。按照 RFC 2187 描述的 Squid/Harvest 行为,收到允许的查询后,cache 会检查 URL 是否存在于本地缓存,并依据本地 refresh 或 TTL 规则判断该条目是否至少在随后短时间内仍属 fresh,满足条件才返回 ICP_OP_HIT。对查询者而言,HIT 的直接含义很窄:随后迅速发出的 HTTP 请求预期会在该 peer 命中。
但 RFC 同时承认竞态条件:在 ICP_OP_HIT 发出后、HTTP 请求真正到达前,对象仍可能被清除。于是,HIT 不是不可撤销的承诺,也不是持久容量证明。它是一次时点判断。
它也不是端到端的新鲜度证明。RFC 2187 自己指出,ICP 与 HTTP 的表达能力差异很大:ICPv2 不携带 HTTP 方法,也无法表达 If-Modified-Since 以及 HTTP/1.1 的完整 Cache-Control 语义。尤其 ICP_OP_HIT_OBJ 可以直接在 ICP 响应中携带小对象,但因为它可能无法满足 HTTP 请求头约束,文档明确不鼓励依赖这一功能。于是,“对象已经返回”仍不能自动推出“这个对象满足当前 HTTP 请求的全部语义条件”。
这也是不能把 ICP 的 HIT 与一般性的 cache-control 混为一谈的原因。RFC 3040 把 cacheable 定义为某响应是否允许被缓存并用于后续等价请求,并把具体可缓存性规则归于 HTTP;RFC 2187 则讨论邻居之间如何用 ICP 交换“对象似乎在这里”的提示。前者关心存储与重用的 HTTP 语义,后者关心下一来源选择。一个 HIT 可以参与路由式选择,却不会替代关于响应是否可用、是否需要验证、是否受请求指令限制的 HTTP 判断。
RFC 3143 对缓存 mesh 的已知问题进一步说明,路径变化甚至可能让用户看到比先前请求更旧的内容。它讨论的“序列化”问题表明,mesh 内部的多个可选路径会把“我能从某 cache 得到对象”与“用户获得一致、符合预期的对象版本”分离开。HIT 是局部可得性证据,不是整个系统状态的一致性证明。
MISS 不是失败,而是下一权限边界
MISS 在 RFC 2187 中的含义同样依赖角色。对于 sibling,MISS 被查询者可以返回,但查询者随后应忽略它作为转发候选,因为 sibling 无权承担这个 MISS。对于 parent,MISS 却可能是一种继续取回对象的邀请:即使 parent 本地没有对象,它仍可作为 transit 继续向源站或上层取得资源。
这种差异让 MISS 成为理解“授权边界”的最佳例子。若只看消息内容,两个 peer 都可能返回 ICP_OP_MISS;但只有结合本地关系配置,查询者才知道哪个 MISS 可以变成下一跳。RFC 2187 还定义了 ICP_OP_MISS_NOFETCH,用来表示“这里 MISS,而且不要通过我继续取”。收到这种响应后,cache 不应把请求转发给该 peer。可见,MISS 不是简单的“没有”,而是“没有”与“是否允许继续代取”两个问题的交叉点。
当所有可用 peer 都 MISS 时,RFC 2187 给出的决策顺序也没有把结果简化为“选最快的”。实现可以考虑带源站 RTT 信息的 parent,可以保留 FIRST_PARENT_MISS,也可以在没有合适 parent 时直接访问 origin;若 firewall 阻止直连,则又必须依赖允许穿越边界的 parent。决定来源的是一组条件与回退,而不是单一距离度量。
更值得注意的是,Squid 对 parent MISS 的 RTT 可以加权,因为“最近的 parent 未必是人们想用的那个”。这句话几乎直接否定了把 ICP hierarchy 当成最短路径协议的读法。权重本身是管理意图的投影:运营者可以有成本、可靠性、管理边界、网络政策等理由不选择 RTT 最低者。RFC 没有替部署者定义这些目标函数。
低时延也不等于低成本或最快完成
如果把第一个返回 HIT 的 peer 当作“最佳”,异构网络会很快暴露这种推理的问题。RFC 3143 给出一个典型案例:一个 sibling 链路带宽高但时延大,另一个带宽低但时延小。低时延 peer 的 ICP_HIT 会先到,但对较大的对象,真正的对象传输反而可能从高带宽 peer 更快完成。于是“控制消息先回来”与“用户更快拿到内容”不是同一个指标。
因此,测得的 ICP RTT 只能证明一类很具体的时间关系。它不能单独证明总传输时间,不能证明带宽充足,也不能证明最低网络成本,更不能证明容量在未来请求中仍然存在。配置权重也一样:权重表明运营者对选择函数做了人为修正,却不说明权重背后的商业理由,更不说明被加权的一方同意同一套偏好。
RFC 2187 还把未收到 ICP reply 视为一种即时可达性提示:可能是路径拥塞或中断,也可能是对方 cache 应用没有运行。这个信号足以支持“此刻别用这个邻居”的操作决定,却不足以诊断根因。没有响应既不等同于长期故障,也不自动说明对方撤销了 peering。协议所见,只是当前一次轻量查询没有得到预期回复。
多播成员资格不构成信任
RFC 2187 对 multicast 的讨论把“能听见”与“被信任”分得更彻底。cache 可以把 ICP 查询发送到 multicast address,加入组的邻居都能收到;但加入多播组不需要特殊权限,也无法阻止第三方加入。因此,文档明确要求不要自动信任任何对 multicast 查询作出响应的 cache,并建议忽略来自未被明确配置为邻居的地址的 ICP 消息。
这意味着多播成员资格只证明某个系统位于消息可达范围内并选择加入组,不能证明它属于既定业务关系,更不能证明其内容可信。RFC 2187 给出的攻击图景很直接:一个非法 cache 可以加入组,对所有请求都返回 HIT,再交付伪造内容。于是,多播中的“我有”如果脱离已知邻居名单和访问控制,甚至可能成为诱导流量的手段。
同样,返回地址也不是经认证身份。RFC 2187 明确指出 ICPv2 没有 authentication fields,并讨论了 IP spoofing 风险;其第一道防线是根据消息来源地址和已知邻居配置过滤。这里能得到的是“实现依赖来源地址与本地信任配置做筛选”,而不是“ICP 原生证明了远端身份”。这一区别对于今天阅读老协议尤其重要:地址可识别性与密码学身份验证不是一回事。
RFC 2186 规定消息,不赋予商业或组织权力
RFC 2186 的范围更窄。它是 Informational RFC,并明确说明自己只描述 ICPv2 报文格式和字段,而将 Web caching 中的应用留给 RFC 2187。20 字节固定头、Opcode、Version、Message Length、Request Number、Options、Sender Host Address 与 Payload,以及 ICP_OP_QUERY、ICP_OP_HIT、ICP_OP_MISS、ICP_OP_MISS_NOFETCH、ICP_OP_DENIED、ICP_OP_HIT_OBJ 等操作码,解决的是报文如何被表示和区分。
这层边界不能被跳过。一个操作码能编码“命中”“未命中”“拒绝”“不要通过我继续抓取”,却不能凭空建立 parent/sibling 合同;Sender Host Address 字段也不等于经过认证的组织身份。RFC 2186 甚至提醒 Sender Host Address 不应优先于底层套接字获得的地址信息,而且实践中并未使用。报文字段提供协议语义,不提供更高层的授权来源。
同理,Request Number 可以把响应与查询关联起来,却不是审计意义上的交易凭证;ICP_FLAG_SRC_RTT 可以携带 RTT 信息,却不是价格、结算或 SLA;HIT_OBJ 能携带对象,却不是内容安全认证。这些字段的语义必须停留在协议定义的边界内。
RFC 9211 观察交付过程,但不回填 ICP 的旧语义
2022 年的 RFC 9211 定义 Cache-Status 响应头,用标准化方式描述 cache 如何处理请求和响应。它的 hit 表示请求由 cache 满足、没有向前转发;fwd 表示请求向 origin 方向继续,并可说明是 uri-miss、stale、bypass 等原因。多个 cache 的成员还可以按处理链保留下来,为调试提供跨层观察。
这是一种交付可观测性,而不是对 1997 年 ICP 邻居选择机制的重新定义。Cache-Status 发生在 HTTP 响应语境中,用来说明实际处理发生了什么;ICP 查询发生在来源选择阶段,用来给下一步决策提供提示。一个更接近“事后轨迹”,另一个更接近“事前局部信号”。把两者混起来,会把“某层报告它命中了”误读成“之前的 peer 选择必然最优”,或者把“请求向前转发”误读成“某 parent 在组织层面拥有长期转发义务”。
RFC 9211 也没有把 cache 标识符升级为认证身份。它允许成员标识是产品名、服务名、主机名、IP 地址或生成字符串;同时提醒 Cache-Status 本身可能暴露 cache 行为,帮助攻击者推断活动或实施时序与 cache poisoning 相关攻击,因此部署者可以选择不发送,或只对获授权客户端发送敏感信息。可观测性增加了证据,却仍是有选择、有限度的证据。
从缓存代理到 CDN:经济关系不能从技术信号倒推
RFC 3040 的分类法提供了另一个必要区分。它把 caching proxy 描述为“对客户端表现为 server、对 server 表现为 client”的带缓存代理;又把 surrogate 定义为由一个或多个 origin server 授权、代表其工作的网关,通常与 origin 紧密协作。这里的“delegated authority”与 RFC 2187 中的 parent/sibling peering 不是同一概念。
这对于现代 CDN 讨论尤其重要。今天人们看到边缘节点、缓存命中、源站回源和多层缓存,很容易把早期 cache hierarchy 直接解释成 CDN 商业结构。但这六份 RFC 并没有定义现代 CDN 的计费模式、流量承诺、结算关系、客户合同、容量采购或利润分配。它们能帮助解释技术角色,不能替代经济证据。
因此,一次成功从某 peer 取到对象,最多说明该请求在当时通过某条被允许的技术路径完成;它不能证明双方存在长期互惠,也不能证明流量成本最低,更不能证明未来峰值时仍有相同容量。一个 surrogate 的授权概念也不能反向证明任何特定 parent/sibling 关系具有相同商业性质。技术拓扑与商业拓扑可能重叠,但不能互相替代。
最重要的阅读方法:每个信号只回答一个较小的问题
如果把这些 RFC 放在一起看,会得到一种比“老缓存协议史”更有普遍性的分析纪律:每个观测值都应只回答它被设计来回答的问题。
邻居标签回答的是本地配置如何称呼一个关系,不证明对端采用相同标签;HIT 回答的是某 cache 此刻认为对象可由自己满足,不证明端到端新鲜度或语义适配;MISS 回答的是本地未能命中,不自动回答是否允许 transit;RTT 回答的是某类控制或网络往返延迟,不回答完整对象传输成本;多播成员资格回答的是消息接收范围,不回答信任;返回对象回答的是数据到达某个协议环节,不回答内容认证与所有 HTTP 条件;一次成功抓取回答的是一次执行成功,不回答下一次的容量、政策或可用性。
RFC 2187 本身就把部署者留在决策中心:管理员决定哪些请求使用 ICP、哪些 peer 被查询、谁是 parent 或 sibling、哪些域直连、何时停止层级、等待多久、是否启用 RTT 或 HIT_OBJ 选项、如何穿越 firewall、如何限制 multicast 范围,以及没有合适回复时怎样 fallback。协议提供信息,配置赋予信息行动意义。
这也是该文档今天仍值得读的原因。它展示了分布式系统中一种常被忽略的边界:观察到某个事件,与拥有让该事件发生的权力,是两回事;拥有一次权力,与承担长期义务,又是两回事。只有把“证据”“授权”“策略”“结果”分开,HIT 才不会被写成契约,时延才不会被写成成本,邻居才不会被写成信任,成功才不会被写成必然。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
