SETTINGS 与优先级

六个 SETTINGS 参数、ACK 机制,以及优先级树的废弃与 RFC 9218 扩展优先级。

作者 David更新于 第 7 篇(共 16 篇)

SETTINGS 帧

连接级参数协商,流 ID MUST 为 0。

机制要点:

  • 不是握手,是单向声明:每一端各自声明「我这边的接收能力」。双方的值互相独立,无需一致。
  • 载荷是若干 6 字节条目:2 字节标识符 + 4 字节值。载荷长度不是 6 的倍数 → FRAME_SIZE_ERROR。
  • 接收方 MUST 立即(在处理后续帧之前)应用这些值,并回一个置 ACK 标志(0x01)的空 SETTINGS。
  • 带 ACK 的帧载荷长度必须为 0,否则 FRAME_SIZE_ERROR。
  • 长时间收不到 ACK MAY 以 SETTINGS_TIMEOUT 关闭连接。
  • 未知标识符 MUST 被忽略(扩展点)。

六个标准参数

ID名称默认值语义
0x01HEADER_TABLE_SIZE4096对端 HPACK 动态表上限(字节)
0x02ENABLE_PUSH1是否允许服务端推送;只能取 0/1,其他值 → PROTOCOL_ERROR
0x03MAX_CONCURRENT_STREAMS无限对端可同时打开的流数
0x04INITIAL_WINDOW_SIZE65535流级流量控制初始窗口;> 2^31−1 → FLOW_CONTROL_ERROR
0x05MAX_FRAME_SIZE16384可接收的最大帧载荷;合法范围 16384 – 16777215,越界 → PROTOCOL_ERROR
0x06MAX_HEADER_LIST_SIZE无限可接收的字段列表未压缩大小上限(含每字段 32 字节开销);仅为建议

生产调优的三个重点:

  1. INITIAL_WINDOW_SIZE —— 默认 65535 在高 BDP 链路上严重限速,通常调到 MB 级。
  2. MAX_CONCURRENT_STREAMS —— 默认无限意味着无防护,必须设有限值(常见 100–128),否则易受流洪泛。
  3. MAX_HEADER_LIST_SIZE —— 默认无限,是 HPACK 炸弹的防线,应显式设置。

优先级:一段被推翻的设计

RFC 7540 的优先级树(已废弃)

原设计中,PRIORITY 帧与 HEADERS 的优先级字段可构建一棵依赖树:

  • 每个流可声明依赖另一个流(Stream Dependency)。
  • 同层兄弟按权重(1–256)按比例分配带宽。
  • 支持独占依赖(E 标志),把原有兄弟全部改挂到自己名下。

RFC 9113 已将其全部废弃(deprecated)。废弃原因,逐条:

问题说明
过度复杂服务端要维护每连接一棵可变树,含已关闭流的「幽灵节点」
实现分歧大各服务端调度策略互不兼容,客户端无法预期效果
浏览器各行其是Chrome 用线性链、Firefox 用分组树,服务端难以同时优化
收益不明实测多数场景与简单的 FIFO/轮转差别不大
攻击面恶意构造的深树消耗服务端内存与 CPU

现状:端点仍 MUST 能解析这些字段(向后兼容,收到即忽略),但 SHOULD NOT 再生成。多数现代服务端直接无视优先级树。

RFC 9218 扩展优先级(现行方案)

替代方案把优先级从「二进制帧里的树」改成了普通的 HTTP 字段,且 h2 与 h3 通用:

priority: u=1, i

两个参数(结构化字段语法):

参数类型取值语义
u整数0–7,默认 3紧急度,数值越小优先级越高
i布尔默认 falseincremental:为真表示可渐进式呈现(如渐进 JPEG、HTML 流式渲染)

用法:

  • 客户端在请求的 priority 字段中声明。
  • 服务端可在响应中用 priority 字段覆盖(服务端更清楚资源性质)。
  • 也可用 PRIORITY_UPDATE 帧(h2 类型 0x10,h3 类型 0xF0700/0xF0701)在请求发出后动态改。
  • i=?1 的同优先级流应轮转调度(让多个可渐进资源同时推进);i=?0 的应顺序完成(一个一个来,早点可用)。

设计上的进步:无状态、可读、可被中间件理解、h2/h3 统一——而不是一棵需要双方精确同步的树。

下一篇:连接管理与错误码。

本页目录