题干与适用场景
服务启用了 TLS 1.3 的 0-RTT,以减少恢复连接的首包延迟。某些请求可能在握手完成前到达,而早期数据可能在另一条连接被重放。请说明 API 何时应返回 425 Too Early,客户端如何重试,以及网关和所有服务实例如何保持一致。
这道题适合后端、网络、基础设施和安全岗位。重点不是背状态码,而是把传输层的重放风险映射到具体资源和副作用,明确 425、延迟处理、禁用早期数据、幂等键与审计之间的边界。
面试官考察点
强回答会指出 425 表示服务器不愿冒险处理可能被重放的请求,不是普通过载、认证失败或业务校验错误。它会区分安全方法与有副作用的方法,说明只有源站知道资源是否能接受早期数据,并解释 Early-Data 头、客户端重试、网关转发和多实例一致性。最后还要覆盖重试风暴、跨实例状态和不可逆副作用。
回答前需要澄清的问题
- 请求是否真的来自 early data,或是否带有可信的
Early-Data: 1? - 操作是否改变状态、扣款、发货、发消息或触发外部副作用?
- 客户端是否能在握手完成后安全重试,是否有幂等键和去重存储?
- 中间网关是否理解 425 和 Early-Data,所有源站实例的策略是否一致?
- 连接恢复、负载、超时和重试预算如何影响安全与可用性?
30 秒回答框架
“425 是对可能重放的 early-data 请求做的安全拒绝,不是通用限流。源站按资源风险决定:无副作用或可证明幂等的请求可以延迟或继续处理,扣款、写入和其他不可逆动作应等待握手完成,必要时返回 425。客户端收到 425 后只能在握手完成后重试;网关必须保留信号,所有实例采用一致策略,并用幂等键和服务端去重保护重复请求。”
分步骤深入解答
第一步:识别 early data 和重放模型
TLS 1.3 0-RTT 让客户端在握手完成前发送应用数据。握手完成只能说明当前连接上的数据没有被重放,不能证明另一条连接没有收到同一份数据。因此服务不能只看连接成功,就假设请求唯一。
第二步:按资源副作用分类
源站最清楚资源的重放后果。读取、查询或没有状态变化的操作通常风险较低,但也要确认响应和计费逻辑没有隐藏副作用。创建订单、扣款、发放优惠、修改权限和发送消息都可能重复执行,应拒绝或延迟到握手完成后处理。
第三步:选择延迟、拒绝或关闭 0-RTT
RFC 8470 给出三类保护:在 TLS 层拒绝早期数据、等待握手完成后再处理,或用 425 要求客户端稍后重试。三者都能降低重放风险;选择取决于资源级策略、内存预算、客户端能力和负载。不要把 425 当成每次握手失败的替代错误码。
第四步:正确发出 425
当请求来自 early data 或带有 Early-Data: 1 且不能安全处理时,源站返回 425。425 默认不可缓存,响应体不是某个资源的表示。源站不应在客户端没有重试能力或请求不是 early data 时随意发出 425,否则客户端可能无法恢复。
第五步:定义客户端重试边界
使用 early data 的客户端收到 425 后应重试,但重试不能再次使用 early data。客户端应保留请求语义、限制次数、使用退避并遵守取消和超时。若请求本身不可安全重试,客户端应向调用方报告失败,而不是无限重放。
第六步:让网关转发信号
网关通常不知道某个资源是否允许 early data。转发可能有重放风险的请求时,它必须保留或补上 Early-Data: 1,不能删除这个信号。若源站不支持该机制,网关应等待握手完成或直接拒绝;只有在明确知道重试安全时才可以代替客户端重试。
第七步:保证多实例一致
所有源站实例、边缘节点和异步处理器都要采用一致的早期数据策略。一个实例延迟而另一个实例直接扣款,会让攻击者或网络路径利用差异制造重复副作用。策略版本、幂等键、去重记录和可观测字段应跨实例共享。
第八步:验证重试与高负载行为
测试完整握手、重放到另一实例、部分请求在握手前到达、网关转发、客户端超时和服务器过载。记录 early-data 命中率、425 比例、重试次数、重复键、重复副作用和队列增长。高负载时,反复返回 425 或 503 都可能放大重试流量,应设预算并可整体关闭 0-RTT。
设计取舍与边界
0-RTT 的收益是降低恢复连接的首包等待,代价是服务必须承担重放分析、策略一致性和额外去重。按方法名判断安全不够,因为安全方法也可能触发计费、审计或缓存写入;按资源配置风险更可靠。
幂等键能减少重复副作用,但不能让任意请求自动适合 early data。去重状态必须有足够保留期、跨实例可见,并明确键冲突、重试超时和存储故障时的行为。对不可逆动作,等待握手完成通常比依赖复杂补偿更清晰。
落地计划与证据
先为每类资源登记 early-data 策略:允许、延迟或 425。为写操作增加幂等键和去重记录,网关统一传递 Early-Data,源站在日志中记录连接状态、策略版本和重试关联。随后做跨实例重放演练,验证订单、扣款和消息不会重复。
上线后按资源和客户端版本观察 425、重试与副作用指标。若客户端不遵守重试约束,优先修复客户端或在边缘关闭 0-RTT,而不是放宽源站保护。RFC 8470 还要求在网关和源站之间保持一致,发布检查应覆盖每个入口。
常见误区与追问
把 425 当成限流或服务过载
425 针对可能被重放的 early-data 请求;并发过高、依赖不可用或资源配额不足应使用各自的错误语义和退避策略。
看到 POST 就一定返回 425
方法名只是线索。真正判断依据是该资源是否能承受重放,以及是否有可靠的幂等与去重。某些可证明幂等的写操作可以延迟处理或采用资源级策略。
发送 425 后又用 0-RTT 重试
RFC 8470 要求收到 425 的重试不能再次使用 early data。否则客户端会把服务器的保护变成新的重放机会。
网关删除 Early-Data 头
网关删除信号会让源站误以为请求未经历 early data。它应保留或补上该头,并确认源站理解 425;不确定时等待握手完成。
如何证明没有重复扣款?
用跨实例共享的幂等键、请求指纹和扣款状态机做一次重放演练,核对每个业务操作只产生一个最终结果。还要测试去重存储不可用、客户端超时后重试和消息下游重复投递,不能只看 HTTP 状态码。