题干与适用场景
网关与客户端都支持 HTTP/2,实时服务希望在同一条连接上复用 WebSocket 流,减少 HTTP/1.1 独立连接。请设计 RFC 8441 迁移方案,说明握手、能力协商、代理兼容、流与连接关闭、回退及验收。核心考察 HTTP/2 扩展连接语义与生产迁移,归为 backend。
面试官考察点
- 能否说清 Extended CONNECT 与 HTTP/1.1 Upgrade 的差异。
- 能否正确使用
:protocol与SETTINGSENABLECONNECT_PROTOCOL。 - 能否区分 HTTP/2 stream 关闭和底层连接关闭。
- 能否设计不支持扩展的代理和客户端回退。
- 能否用握手成功率、流错误和连接复用指标验收。
回答前需要澄清的问题
- 客户端、边缘代理、服务网关和 origin 是否都支持 RFC 8441?
- 是否允许同一 HTTP/2 连接混合普通请求与 WebSocket 流?
- 负载均衡器是否会重建 HTTP/2,还是端到端透传?
- 旧客户端能否继续走 HTTP/1.1 Upgrade?
- 需要迁移的是浏览器 WebSocket、原生 SDK,还是内部 RPC?
30 秒回答框架
“我先确认每一跳是否发送并接受 SETTINGSENABLECONNECTPROTOCOL。支持时客户端发 Extended CONNECT 并带 :protocol = websocket,服务端返回成功后把该 stream 当作 WebSocket 字节流;不支持时回退到 HTTP/1.1 Upgrade。普通请求与 WebSocket 可复用同一 HTTP/2 连接,但 stream 级取消不能误关整条连接。灰度记录握手、回退、RSTSTREAM、连接复用和消息延迟。”
分步骤深入解答
第一步:协商扩展能力
RFC 8441 要求端点通过 HTTP/2 SETTINGS 参数表明支持 Extended CONNECT。客户端只有在确认对端能力后才发送带 :protocol 的 CONNECT;中间代理若不透传 SETTINGS,必须让客户端走回退路径。
SETTINGS_ENABLE_CONNECT_PROTOCOL = 1
:method = CONNECT
:protocol = websocket
:authority = chat.example这些字段表达握手结构,具体帧序列仍按 HTTP/2 和 RFC 8441 验证。
第二步:处理握手与数据流
成功的 Extended CONNECT 建立一个 HTTP/2 stream,后续数据承载 WebSocket 帧语义。它不使用 HTTP/1.1 的 Connection、Upgrade、Sec-WebSocket-Key 和 101 路径;服务端要验证权限、origin、子协议和扩展,再返回成功状态。
第三步:区分 stream 与 connection 生命周期
单个 WebSocket stream 被取消时发送 RST_STREAM 或完成流关闭,不应关闭同一 HTTP/2 连接上的普通请求。GOAWAY 只影响新 stream,已有 stream 需要按服务策略完成、迁移或重连;客户端重连要避免把旧 stream 的消息重复提交。
第四步:设计代理回退
建立客户端、CDN、负载均衡器、服务网关的能力矩阵。任何一跳不支持时,使用 HTTP/1.1 Upgrade 或明确失败,不要把 :protocol 当普通 header 转发。回退必须保留鉴权、origin 校验、子协议和心跳语义。
第五步:控制流量与背压
HTTP/2 流量窗口和 WebSocket 应用队列同时存在。发送端不能只看应用缓冲区;要监控 stream/window 阻塞,设置每连接和每流上限,并在关闭时丢弃或重放策略明确。单个慢流不应阻塞同连接的普通请求。
第六步:灰度和安全检查
先在内部客户端和单一区域启用,比较 HTTP/2 Extended CONNECT 与 HTTP/1.1 Upgrade 的握手成功率、首消息延迟、重连率、RST_STREAM、GOAWAY 和代理错误。继续执行 TLS、origin、认证、子协议和消息大小限制,扩展连接不会自动改变 WebSocket 安全模型。
第七步:定义回滚与验收
保留按客户端或区域关闭 HTTP/2 WebSocket 的开关。验收需覆盖代理不支持、SETTINGS 缺失、拒绝的 :protocol、stream 取消、GOAWAY、网络切换和重复重连。结果至少比较连接成功率、消息顺序、p95 延迟、连接数和回退比例。
高质量示范回答
“我会先建立端到端能力矩阵,确认每一跳支持 SETTINGSENABLECONNECT_PROTOCOL。支持时发送 Extended CONNECT 与 :protocol = websocket,成功后在该 HTTP/2 stream 上承载 WebSocket;不支持时回退到 HTTP/1.1 Upgrade。鉴权、origin、子协议、心跳和消息大小限制保持不变。
生命周期上,RSTSTREAM 只影响一个 WebSocket,GOAWAY 影响新 stream,不能误关同连接的普通请求。灰度记录握手成功率、回退、RSTSTREAM、GOAWAY、重连、首消息 p95、连接复用和代理错误,并注入 SETTINGS 缺失、拒绝协议、慢流和网络切换场景。只有结果顺序一致且回退可控,才扩大范围。”
常见错误
- 把 Extended CONNECT 当普通 header → 代理可能拒绝或错误转发 → 验证 SETTINGS 与伪首部。
- 继续发送 HTTP/1.1 Upgrade 头 → HTTP/2 语义不接受 → 按 RFC 8441 握手。
- RST_STREAM 关闭整条连接 → 影响其他请求 → 区分 stream 与 connection。
- 忽略 GOAWAY → 新旧流处理混乱 → 定义完成、迁移和重连。
- 只测直连 → CDN/LB 能力差异导致生产失败 → 做逐跳矩阵。
- 迁移后放宽鉴权 → 扩展连接仍暴露 WebSocket 风险 → 复用原安全策略。
追问及应对
追问一:为什么不直接用 HTTP/3 WebSocket?
HTTP/3 有 RFC 9220 的独立方案;若现有链路是 HTTP/2,RFC 8441 可先复用连接和代理体系,选择应基于端到端支持与迁移成本。
追问二:SETTINGS 没有开启时能否试发?
不应试发。客户端应等待能力信号,否则收到协议错误;产品层回退到 HTTP/1.1 或报告不支持。
追问三:GOAWAY 后如何避免消息重复?
为消息设置客户端序号或幂等键,记录已确认偏移,重连后从明确位置恢复,不能假设旧 stream 已完成全部发送。
追问四:如何定位代理不兼容?
逐跳抓取 SETTINGS、CONNECT 响应和错误码,按 CDN、负载均衡器、区域和客户端版本拆分指标。