---
title: HTTP/3
url: https://doc.liz6.com/networking/06-HTTP/03-HTTP3
locale: zh
area: networking
tags:
- networking
- HTTP
date: 2026-06-30
modified: 2026-06-30
description: HTTP/3 在 QUIC 上跑 HTTP——不再依赖 TCP,用 UDP 封装,stream 之间完全独立(无队头阻塞)。QPACK 替代 HPACK,0-RTT 恢复连接。HTTP 语义没变,传输层彻底重写。
---

# HTTP/3

> HTTP/3 在 QUIC 上跑 HTTP——不再依赖 TCP,用 UDP 封装,stream 之间完全独立(无队头阻塞)。QPACK 替代 HPACK,0-RTT 恢复连接。HTTP 语义没变,传输层彻底重写。

## 概述

HTTP/3（RFC 9114, 2022）将 HTTP 从 TCP 迁移到 QUIC（UDP），解决了 HTTP/2 最大的遗留问题——TCP 层队头阻塞。一个 stream 的丢包不再阻塞其他 stream。QUIC 的连接迁移还使移动网络切换（WiFi↔4G）不再断开 HTTP 连接。QPACK 替代 HPACK 解决了 header 压缩的动态表 HOL 阻塞。HTTP/3 使用了与 HTTP/2 完全相同的语义——只是换了传输层。

## HTTP/3 = HTTP/2 semantics + QUIC transport

HTTP/3 保留了 HTTP/2 的全部语义 (streams, multiplexing, headers, methods, status codes) 但换掉了传输层: TCP → QUIC (UDP)。

主要变化:
- Stream: 不再是 TCP byte stream 上的 frame multiplexing → QUIC 的 stream 是协议首层
- HPACK → QPACK: 解决 HPACK 的"动态表更新丢失 → HOL blocking"
- TLS 1.3: 强制 (QUIC 内建加密, 无明文的 HTTP/3)
- Server Push: 已废弃 (Chrome/nginx 均已移除)

## QPACK

HPACK 的问题: 如果包含动态表更新的 HEADERS frame 丢了 → 接收方无法解码后续 HEADERS → HOL blocking again!

QPACK: 动态表更新和数据帧在 QUIC 的**不同 unidirectional streams** 上传输:

```
  Encoder Stream (单向, QPACK encoder → decoder):
    表更新: Insert (name, value) + TSS (Table State Synchronize)
  
  Decoder Stream (单向, decoder → encoder):
    Feedback: Section Acknowledgment, Stream Cancellation

  请求/响应流 (bidi):
    HEADERS + DATA frames (引用动态表 index)

  → 表更新的丢包只阻塞 Encoder Stream (表更新), 不阻塞请求/响应!
```

## 部署: Alt-Svc

```
HTTP/2 or HTTP/1.1 response header:
  Alt-Svc: h3=":443"; ma=86400

  h3: HTTP/3 over QUIC
  ma (max-age): 86400 秒内记住此 alternative
  :443: QUIC 端口 (通常相同端口)

  Browser: 收到 Alt-Svc → 下次连接到同一 host → 优先尝试 QUIC:443
          → 如果 QUIC 不通 (UDP blocked, QUIC version mismatch) → fallback to TCP
```

## 参考

- **RFC**: 9114, 9204
- **工具**: `curl --http3 -v`, Chrome `chrome://net-internals/#http3`

*Keywords: HTTP/3, QUIC, QPACK, Alt-Svc, connection migration, 0-RTT, unidirectional streams*
