摘要

  • 第 11 版明确规定:只有对端发送了空值 reset_stream_at 传输参数,才可以发送 RESET_STREAM_AT。这是解析许可,不是对应用语义的代签。
  • Reliable Size 表示最低交付量,而非精确截断点或永久承诺。后续值只能下降;乱序到达的旧大值不能把已经缩小的下限恢复。
  • WebTransport 另行要求可靠前缀至少覆盖会话头。正是这条应用层规则,而不是 QUIC 扩展协商本身,保证被中止的流仍带着可归属的身份。

第 11 版处于获批待公告阶段,并不是 RFC

2026 年 9 月 6 日,Marten Seemann 与奥一穂提交了 QUIC Stream Resets with Partial Delivery 第 11 版。Datatracker 将其列为 QUIC 工作组的 Standards Track Internet-Draft,状态同时显示已提交 IESG、IANA 审查为“OK—仍需动作”,以及“已批准、待发送公告”。这些状态说明 IESG 已作出批准决定,却不等于批准公告已经发出,更不等于 RFC 编辑与编号已经完成。本文始终把它称作草案。

这也不是简单续期。第 11 版紧随 9 月 3 日 IESG telechat,吸收了多项评审意见:新增未经对端声明不得发送的规范性禁令;把 Reliable Size 从一般“数量”改成“最低数量”;将“重传帧”改写为重传当前帧所承载的信息;拆开错误码与 Final Size 的一致性规则;澄清乱序时只忽略下限上调而不是丢弃整帧;并调整收到 STOP_SENDING 后的建议。

这些细改把权力边界照亮了。传输参数授予使用一种线格式的权限;重置帧同时陈述错误原因、最终计费字节数和仍需送达的前缀;应用协议决定哪些前缀不可放弃;接收应用又可以撤回继续接收的意愿。把它们统称为“可靠重置”,容易让实现者误以为一个开关已经决定全部行为。

对端先授予使用这种帧的许可

扩展支持通过 reset_stream_at 参数声明。第 11 版给出的参数值是 0x1d,内容必须为空;理解该参数的实现收到非空值时,应以 TRANSPORT_PARAMETER_ERROR 终止连接。新增的关键句更直接:若对端没有声明支持,端点 MUST NOT 发送 RESET_STREAM_AT。

这道闸门排除了许多似是而非的授权来源。某个软件版本包含代码,不代表当前连接启用了它;同一厂商的另一端曾经支持,不代表本次握手同意;发送方相信未知帧会被宽容处理,也不构成许可。当前连接中由对端发送的传输参数,才是可以使用帧类型 0x24 的权威记录。

0-RTT 把时间因素带进来。双方必须记住服务器上次是否声明该扩展;若服务器接受早期数据,就不能在恢复连接中撤销它。否则客户端会依照旧握手留下的权限发送,而服务器一边接受相同的早期数据上下文,一边否认当初的能力。服务器可以拒绝 0-RTT;不能在接受它的同时悄悄改写这项扩展事实。

不过,这个参数只证明“可解析”。它没有说明某段前缀对应用意味着什么,没有保证中继能够归属一条出错的流,也没有保证第一次出现的正数下限永远维持正数。

Reliable Size 是可以向下移动的地板

RESET_STREAM_AT 依次携带 Stream ID、Application Protocol Error Code、Final Size 与 Reliable Size。Final Size 维护 QUIC 对发送方最终产生多少字节的统一记账;Reliable Size 表示即使发生重置,也必须交付给接收应用的最短前缀。若 Reliable Size 大于 Final Size,接收方以 FRAME_ENCODING_ERROR 关闭连接。

第 11 版刻意加入“minimum”。小于该偏移的丢失 STREAM 数据必须重传;大于该偏移的数据原则上不应继续重传,但如果字节已经到达,QUIC 栈仍可能把它们交给应用。因此这个字段不是一把删除刀。实现若为了让观测字节数恰好等于字段值而抹掉已到达数据,反而创造了规范没有给出的语义。

更容易被忽略的是,下限可以后退。发送方可再次发送更小的 RESET_STREAM_AT;也可发送普通 RESET_STREAM,其交付效果等同于把 Reliable Size 降到零。数值只能减小,不能重新放大。当前最小值所代表的信息以及低于该值的所有数据,必须持续重传直至确认。

这是一项单向选择权:发送方可以放弃先前承担的部分交付义务,却不能在放弃后重建更大的保证。接收端的现实不是“曾见过的最大承诺”,而是“至今收到的最小有效值”。若产品界面只显示首次值,运营者会把已经失效的承诺当成当前状态。

乱序不能恢复旧承诺

假设发送方先承诺 120 字节,后来降到 24 字节。承载 24 的包先到,承载 120 的旧包后到,是 QUIC 网络中完全正常的顺序。第 11 版要求接收端继续使用 24,并只忽略试图把 Reliable Size 抬高的那一部分。

第 10 版写的是“忽略增加 Reliable Size 的 RESET_STREAM_AT 帧”。评审者指出,照字面忽略整帧,也会跳过对 Application Error Code 和 Final Size 的检查。第 11 版把三个陈述拆开:后到的大值不能生效;后续重置帧的错误码必须一致;重置帧以及带 FIN 的 STREAM 帧,其 Final Size 必须一致。错误码变化触发 STREAM_STATE_ERROR,最终大小变化触发 FINAL_SIZE_ERROR。

同一帧容纳多个字段,不表示这些字段共享同一个新旧判断。Reliable Size 可能因乱序而陈旧,错误码和最终大小却仍是需要验证的证据。把整帧粗略标记成“旧”再丢弃,会把应当暴露的状态冲突一并掩埋。这正是现实分层原则在解析器里的具体形态。

不可缩减的前缀必须由应用协议命名

传输草案明确允许应用协议设定最低阈值,禁止 Reliable Size 降到其下。QUIC 只看见偏移量,不知道开头几个字节是会话 ID、订阅归属还是对象类型。部分可靠性要变成可用语义,必须由上层指出“少于多少便等于没有交付”。

WebTransport over HTTP/3 给出了最清楚的例子。当前第 16 版要求,当实现重置 WebTransport 数据流时,必须使用 RESET_STREAM_AT,且 Reliable Size 至少覆盖 WebTransport header。原因不是偏好更多可靠字节,而是要把将该流关联到某个 WebTransport 会话的 ID 交给接收端。没有这个身份,接收方看到一条中止流,却可能不知道错误与资源该记到哪个会话。

Media over QUIC Transport 第 17 版采取相近但不完全相同的强度。它说使用 RESET_STREAM_AT 时,Reliable Size 应覆盖 subgroup stream header,使订阅者能识别订阅,并在处理 PUBLISH_DONE 时核算被重置的数据流。若没有合适下限,订阅状态可能一直保留到超时。

MUST 与 SHOULD 的差异不能在摘要中抹平。它反映的是各自应用协议对失败与退出的治理选择,而不是 QUIC 内部矛盾。可复用的传输扩展可以允许下限下降;使用它的每个协议都要决定:前缀丢失是否可接受、何时允许退出、身份缺失会泄漏哪些状态。reset_stream_at 协商无权替 WebTransport 或 MoQ 作答。

STOP_SENDING 把可靠性改写为退出决定

STOP_SENDING 表示接收应用不再希望获得这条流的数据。第 11 版新增的建议是:若端点仍以 RESET_STREAM_AT 回应,应把 Reliable Size 设为零,因为对端已经表示不会处理更多流数据。

这条建议消除了实际张力。接收方已撤回兴趣,发送方若继续为正数前缀重传,会消耗拥塞窗口、流控额度、缓冲区与状态寿命,却没有仍愿意接收的受益者。降到零提供了回到普通重置行为的规范路径,也再次说明首次 Reliable Size 并非不可撤回的债券。

特定应用仍可有更严的规则。例如中继可能至少需要一段头部,才能把错误转发到另一跳或完成跨跳结算。此时应用协议必须解释为何不能降到零、如何与接收方的停止请求协调,以及谁承担继续保留状态的成本。“可靠”不是压过取消意愿的道德理由,而是一项必须写明受益人和退出条件的有限义务。

重置标签不会抹掉流控与资源承诺

Final Size 仍受 stream-level 与 connection-level flow control 管理。信用不足时,发送方甚至必须推迟发送 RESET_STREAM_AT;越过接收方上限则触发 FLOW_CONTROL_ERROR。该帧会引发 ACK,丢失后需重传其当前信息;下限以内的数据也可能经历多个往返才到齐。

因此,“已重置”不等于“立即释放”。发送侧只有在当前最小 Reliable Size 和其下数据均获确认后,才能进入 Data Recvd;接收侧也要等这些字节收齐。安全章节要求在此之前继续防范资源承诺与耗尽攻击。

成本账本由此出现。下限由发送方选择,缓冲、流控信用、接收处理和时间却由对端提供。应用若轻率规定很长的不可缩减前缀,就是把自身可靠性偏好外部化。监测至少应记录:协商是否成功、首次值与最小值、下限以内的重传字节、Final Size、停止请求时间、完成用时,以及重置后直到超时才释放的状态。一个“reset 已发送”的绿色计数器无法说明这些问题。

分析边界

本次证据证明的是规范内容、修订历史与评审理由,不是部署份额、性能收益、实现正确性或生产事故。我们没有测试浏览器、CDN、QUIC 库、中继或媒体服务。IANA 状态说明尚有登记动作,本文不主张所有请求项目已经成为最终登记。

WebTransport 第 16 版与 MoQ Transport 第 17 版本身也仍是草案。其 MUST 和 SHOULD 说明应用可以如何利用传输钩子,不保证这些原句会原样进入最终标准。第 11 版在出版处理中也仍可能发生编辑变化。

可长期保留的结论很窄:扩展解析许可、发送方当前的最低交付承诺、应用不可缺失的头部,以及接收方停止意愿,是四个不同权威。只有实现、测试与遥测都保持这种区分,running code 才不会被一个漂亮功能名替代。

来源