摘要

  • CDNI Triggers v2 中的 201 Created 只证明下游 CDN 建立了触发器资源,并不证明清除、失效或预置动作已经完成。
  • 第 20 版要求中转 CDN 把更下游的同步 HTTP 拒绝转换成自己状态资源里的异步 Error.v2;错误可以带真正拒绝者的 PID,也可以只显示中转 CDN 自己。
  • 完成、取消、累计计数、离线节点回归和最终用户看到的结果属于不同证据层,不能压成一个“成功”字段。

四条记录,不能只留一条

把一次三级 CDN 清除拆开看。A 向 B 发出请求;B 验证请求、创建资源,返回 201 Created 和一个状态 URI;B 再把动作传给 C;C 发现自己不支持请求中的某个元素,返回 400 Bad Request。

在 A 的原始 HTTP 事务里,请求已经成功。到了 C,动作却被拒绝。两件事可以同时为真,因为它们描述的不是同一个事件。

这正是 2026 年 9 月 2 日发布的 draft-ietf-cdni-ci-triggers-rfc8007bis-20 值得关注的地方。Datatracker 将它列为 CDNI 工作组的活跃 Internet-Draft,状态是 WG Document。草案若获批准将取代 RFC 8007,但它现在不是 RFC、不是 IESG 批准,也不是任何厂商的部署证明。

与 3 月 2 日的第 19 版相比,第 20 版大幅扩充错误处理,尤其明确级联链路中同步拒绝如何变成异步状态。这不是“CDN 第一次可以 purge”的新闻,而是控制证据如何跨越管理边界的更新。

已结束的 HTTP 事务装不下后来的拒绝

如果 B 在创建触发器之前就发现格式错误、权限不足或自己不支持某种动作,它应立即返回 4xx,不创建资源。但 B 一旦接受 A 的请求,A 与 B 的创建事务就结束了。C 后来返回的 4xx 或 5xx 不可能再成为 A 当时收到的 HTTP 状态。

第 20 版因此要求 B 把 C 的拒绝转换成 Error.v2 Description,写进 B 自己的触发器状态资源。C 若先接受、后异步失败,也走这条回传路径。A 需要轮询状态资源,才可能看到 failed 和 eunsupported 等错误代码。

同一个失败在 C 处是一条同步 HTTP 拒绝,在 A 处却是一条由 B 转述的异步记录。自动化如果只存最初的 201,会漏掉失败;如果只存最终错误而丢掉转换路径,也会失去来源链。

更重要的是,错误来源并不必然透明。B 可以在 Error.v2 里带上 C 的 CDN Provider ID,也可以改用自己的 PID,从而遮蔽真正发生错误的下游 CDN。IANA 的 CDNI 参数登记表提供共享命名空间,但登记一个字段不等于强制商业链条披露身份。

“完成”不是一个点,而是一张图

新触发器通常从 pending 开始,进入 active,最后到 complete 或 failed。中转 CDN 只有在自己和所有下游都完成后,才能报告 complete。只要自己或任一分支进入 processed,上游也必须看到 processed。

processed 是一个诚实的可见性边界:下游接受了工作,却不再提供进一步状态更新。它不能被系统悄悄映射成“完成”。草案建议触发器 URI 使用符合 RFC 9562 的唯一 UUID;唯一句柄能防止资源 URI 被重复利用,却不会让动作自动成功。

失败的时序也有意义。某个下游先失败,中转 CDN 仍要等自身与所有下游处理结束,才报告 failed。终态说明的是整张声明处理图收束到哪里,并不等于第一个异常发生的时刻,更不等于用户端已经看到正确内容。

累计数字故意不是唯一对象清单

第 20 版加入受影响对象数、节点数和对象字节数等累计指标。它建议跨本地节点和级联 CDN 累加,并明确不对同一对象在多个节点上的处理做去重。用途是发现范围异常,不是证明唯一对象总量。

所以,“影响 10,000 个对象”可能是 10,000 个不同对象,也可能是 1,000 个对象在十个节点上的处理次数。零也不必然意味着失败:一个没有匹配到已知对象的清除或失效动作,仍可成功完成。

领导者真正需要的是测量定义、重复规则、预期范围和独立结果,而不是一个足够大的数字。把累计工作量当成覆盖率,会让仪表板比协议本身更武断。

取消与删除都不是魔法撤回

草案要求 CDN 回应取消请求,却允许实现不支持真正取消。即使取消被接受,A 看到的 pending 也可能在请求到达 B 前变成 active;已经活跃或处于 processed 的任务也可能在停止动作生效前跑完。cancelling 只证明停止正在进行。

删除更容易损害审计。资源删除后,状态 URI 会返回 404 Not Found。因此,若上游还要查看终态,草案反而建议取消而不是删除。204 No Content 证明的是状态资源被移除,不是已经执行的清除被逆转。

数据范围也有时间边界。清除与失效必须覆盖进入 active 之前取得的数据,应该覆盖当时仍在获取的数据;对处理开始后新取得的数据原则上不应生效,但草案明确提醒上游不要假定该排除总能做到。清除后立刻预置替代内容,若没有执行顺序约束,替代内容本身可能随后被前一个动作清掉。

RFC 6707定义了 CDN 互联的问题空间,RFC 7336描述各接口关系,RFC 7337给出控制接口需求,而 RFC 9110提供 HTTP 方法和状态码语义。它们共同说明:一个接口内的成功,不能越权替另一个处理阶段作证。

离线节点回来时,旧状态不能跟着回来

草案把单个 dCDN 节点暂时不可用视为内部运行状态,不建议仅因此改变触发器的公开状态;节点恢复服务前,应先把自己同步到此前触发动作之后的状态。

这是一种合理抽象,也是一处风险转移。上游可能在看不见离线节点的情况下收到终态,信心取决于下游是否真正完成回归同步。因此,节点恢复后的用户路径探测,与恢复前的触发器状态回答的是两个问题。

菱形级联还可能让同一内容通过不同中转路径到达下游,产生冲突元数据;草案把它视为配置错误。PID 路径可帮助检测环路,却不能保证上游看见完整供应链。

协议正在改进记录,而不是让一条记录代表所有现实。