摘要
- QUIC 的每个流向都是有序字节序列,STREAM 帧边界不会保留为应用消息边界。
- FIN 和 RESET_STREAM 会传达不可变的 Final Size,用于核对已经消耗的流控额度。
- Final Size 不证明字节已被应用读取、解析、提交、补偿或转化为业务结果。
运维面板最容易犯的错误,是把传输事实直接写成业务结论。面板看到已知的 Final Size,便把请求标为完成;但这个值只说明字节序列的终点已经确定。一个流向可以通过携带 FIN 的 STREAM 帧正常结束,也可以通过 RESET_STREAM 突然结束。两者都能形成传输层的记账边界,却都不能单独回答应用是否读取并采取了行动。
QUIC 把每个流向呈现为有序字节序列。STREAM 帧在传输、重传和交付过程中,其边界不会作为边界被保留下来。因此,消息如何划分属于应用协议。帧边界不是请求、记录或事务的天然分隔符。
对于携带 FIN 的 STREAM 帧,Final Size 等于帧偏移加数据长度。RESET_STREAM 则直接携带 Final Size 字段。该值等于已发送最大字节偏移加一;如果没有发送任何字节,则为零。它表示这个流向消耗的流控额度。连接级流控要累加各流向的 Final Size,包括已经终止的流。这里描述的是资源记账,而不是业务成功。
Final Size 一旦确定就不能改变。如果之后出现不同的值,或出现位于该边界及其之后的数据,就可能触发 FINAL_SIZE_ERROR。即使流已经关闭,也可能需要保留状态来发现后续冲突。不可变性保证的是记账一致性,不是交付证明。
接收过程存在多个独立状态。知道 Final Size,不等于已经收到边界前的全部字节;收到全部字节,不等于已经交给应用;交给应用,不等于应用已经读取、解析、提交持久状态、执行回滚或完成业务。RESET_STREAM 更能说明这一点:它可以中断交付,并允许丢弃尚未读取的字节,但不能证明完全没有交付,因为所有数据可能早已进入缓冲区,reset 指示本身也可能被抑制。
数据包确认属于更低层的证据。处理 STREAM 帧要求把其中字节排入供应用使用的队列,却不证明应用已经读取或处理这些字节。同样,Final Size 也不证明相反流向成功,更不证明整条连接完成。
独立证据账本应记录流 ID 和方向、终止形式 FIN 或 RESET_STREAM、reset 时的应用错误码、Final Size 的来源和数值、观察到的最高偏移、连续字节覆盖范围、字节是否进入接收端、是否交给应用或被应用读取、应用协议的消息 framing、持久化提交、补偿、回滚和业务结果,以及为检测 FINAL_SIZE_ERROR 而保留的状态。
还要保持五个维度的分离。TR-046 讨论发送前的流控许可,不是流向结束后的最终记账总额。TR-052 讨论保留消息边界的 DATAGRAM,而这里讨论的是不保留 STREAM 帧边界的有序字节流。TR-053 讨论 CONNECTION_CLOSE 的连接级结束。TR-054 讨论 STOP_SENDING 暴露的取消证据。TR-045 讨论 ACK 对数据包处理的证明范围。它们不能互相替代。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance

