通用面试:如何设计 WebTransport 会话生命周期与优雅关闭?
题干与适用场景
一个实时协作应用需要可靠地传输文档操作,同时发送允许丢失的光标位置和心跳。团队选择 WebTransport,但没有定义连接关闭、网络切换、重连、背压和资源回收。请设计完整会话生命周期,并说明可靠流、不可可靠数据报和 HTTP/3 连接之间的边界。
W3C WebTransport API 同时暴露可靠 streams 与不可靠 datagrams;HTTP/3 数据报由 RFC 9297 定义。高质量回答应把应用会话和底层传输分层,避免把 close() 当成所有消息都已送达的保证。
面试官考察点
- 能否区分会话关闭、单个流关闭、数据报丢失和网络断线。
- 能否设计重连、会话恢复、序列号、幂等和状态快照。
- 能否处理流背压、数据报容量、慢客户端和资源上限。
- 能否定义 close code、reason、超时和可观测性。
- 能否在浏览器兼容性和 HTTP/3 不可用时给出明确边界。
回答前需要澄清的问题
- 哪些消息必须可靠有序,哪些消息可以丢失或只保留最新值?
- 会话是否允许跨网络切换恢复?恢复需要多长时间和多少历史操作?
- 服务端要限制每个用户的并发会话、流数量和数据报速率吗?
- 关闭是用户主动退出、服务端维护、认证失效还是协议错误?
- 浏览器和代理是否都支持 WebTransport over HTTP/3?降级到什么协议?
30 秒回答框架
把应用 session ID 与底层 WebTransport 连接分离。可靠操作走双向或单向流,带序列号和幂等键;光标、心跳等短时状态走 datagrams,并允许丢失。连接异常时保留短期服务端 session,客户端指数退避重连并发送最后确认序号,服务端用快照加增量恢复。主动关闭先停止新消息、排空可靠流、发送 close code,再设置硬超时;所有路径都限制缓冲和资源。
分步骤深入解答
1. 建立应用会话与传输会话
应用 session ID 表示用户在协作房间中的逻辑身份,WebTransport 实例只是一次网络连接。握手完成后服务端验证 origin、认证、租户和权限,创建连接 ID,并把它映射到应用 session。重连可以创建新连接 ID,但不能自动获得别人的 session。
服务端保存最后确认的操作序号、快照版本、订阅和过期时间。连接丢失后进入短暂 suspended 状态,超过 TTL 才释放应用状态。
2. 为消息选择 streams 或 datagrams
文档操作、权限变更和确认消息走可靠流;流内使用明确帧格式、版本、序列号和幂等键。光标位置、实时指标和心跳走数据报,接收端按时间戳或版本丢弃旧值。不要把必须送达的业务事件放入数据报。
数据报不保证到达、顺序或重传,大小受路径和实现限制。应用要测量丢包和延迟,必要时降低频率或只发送最新状态;可靠流则依赖 WritableStream 背压,不无限追加内存队列。
3. 处理背压和慢客户端
每条可靠流设置发送窗口、待确认上限和最大帧大小。写入返回 pending 时暂停生产者,超时则断开或降级非关键订阅。数据报使用令牌桶和每会话配额,丢弃旧光标比阻塞文档操作更合理。
服务端还要限制会话数、流数、并发解码任务和总内存。指标按租户聚合,避免单个慢客户端拖垮事件循环。
4. 设计断线与恢复协议
客户端为每个可靠操作维护本地序列号和幂等键,收到服务端确认后推进 checkpoint。重连握手发送 session ID、最后确认序号和客户端能力;服务端检查 session 所属用户,再返回快照、增量或不可恢复错误。
恢复期间暂停新的副作用操作,避免旧连接和新连接同时提交。服务端可用 epoch 让旧连接的写入失效;恢复完成后再开放生产者。
5. 设计优雅关闭
主动维护时先广播 draining 状态,拒绝新会话,停止产生非关键数据报。可靠流完成当前帧并发送应用层结束标记,服务端等待有限时间后调用会话关闭。浏览器 close() 只表达关闭会话和错误信息,不能替代应用层确认。
close code 分类应区分正常退出、认证失效、过载、协议错误和服务维护;reason 使用短、非敏感文本。硬超时到达后立即释放连接资源,并记录未完成操作数。
6. 认证、权限和网络切换
每次建立或恢复连接都重新验证认证凭证、origin、租户和房间权限。不要仅凭 session ID 恢复。网络切换可能改变地址,应用层恢复通过新连接完成;服务端以 epoch 防止旧路径继续写入。
若浏览器不支持 WebTransport 或 HTTP/3,降级协议必须显式协商,并重新评估可靠性、延迟和安全边界。不要把 WebSocket 的关闭语义直接套用到数据报。
7. 观测与故障演练
记录连接建立、握手失败、关闭 code、reason、流背压、数据报丢弃、重连次数、恢复耗时和未确认操作数,不记录 token 或文档敏感内容。指标按客户端、网络类型和租户切分。
演练服务器维护、移动网络切换、代理阻断 HTTP/3、慢客户端、数据报突发和重复重连。验收标准包括无重复副作用、恢复边界明确、过期 session 被清理和关闭延迟有上限。
高质量示范回答
我会把应用 session 与 WebTransport 连接分开。可靠文档操作使用带序列号和幂等键的 streams;光标和心跳使用可丢失 datagrams。客户端保存 checkpoint,断线后指数退避,用新连接携带 session ID 和最后确认序号恢复;服务端校验用户和租户,用快照加增量补齐,并以 epoch 让旧连接写入失效。
优雅关闭先 draining,停止新消息和非关键数据报,排空可靠流后发送应用层结束标记,再以 close code 关闭并设置硬超时。所有会话、流、缓冲和重连都有限额;监控丢包、背压、关闭原因和恢复耗时。WebTransport 不可用时显式降级,并重新说明能力差异。
常见错误
- 把 datagrams 当作可靠消息,或把
close()当成业务确认。 - 断线后直接新建连接,不携带 checkpoint、epoch 或幂等键。
- 无限缓存慢客户端数据,导致内存和事件循环被拖垮。
- 只按 session ID 恢复,不重新验证用户、租户、origin 和权限。
- 关闭时没有 draining、硬超时和未完成操作审计。
- 忽略 HTTP/3 不可用、代理阻断和浏览器兼容性。
- 将完整 token、文档内容或敏感 reason 写入日志。
追问及应对
哪些数据适合 datagrams?
允许丢失且过期后无价值的数据,例如光标位置、临时姿态和高频心跳。必须送达的业务操作走可靠流。
如何防止重连造成重复操作?
客户端为操作生成幂等键和序列号,服务端按 session 与 epoch 去重,并在确认后推进 checkpoint。
服务端维护时如何关闭?
先停止新会话并广播 draining,停止非关键数据报,排空可靠流,发送结束标记,随后用正常关闭 code 关闭;硬超时强制回收。
session TTL 过期后客户端重连怎么办?
返回不可恢复错误,要求重新认证和重新加入房间。不能凭旧 session ID 延长权限。
数据报过大或丢包严重怎么办?
限制单报大小和速率,缩短或合并状态,只保留最新值;业务事件不能因数据报不可靠而丢失。
如何验证降级没有改变语义?
为每种协议声明可靠性、顺序、恢复和认证差异,运行断线、代理阻断、慢客户端与重复重连测试,并监控副作用重复率。