Files
go-omni/transport/native/HTTP2.md

38 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# native HTTP/2 进入条件
当前 `transport/native` 是经过 Linux 长连接和反向代理验收的 HTTP/1.1 实现。HTTP/2 暂不直接打开,原因是它把一个 TCP 连接变成多个独立请求流,连接级的 Keep-Alive、超时和并发限制不能直接复用现有 HTTP/1.1 状态机。
当前已提供独立的 `transport/http2` 实验 Runner。它已经验证 TLS/h2、h2c、本地连接和请求闸门、GOAWAY 排空以及 RST_STREAM 取消;这些结果用于验证生命周期设计,不代表 native 已经启用 HTTP/2。实验 Runner 还覆盖了默认 1 MiB 头部上限、8 MiB 请求体上限、128 路同连接 stream 多路复用,以及 2 MiB 慢读取 body 在窗口耗尽后的恢复。`TestTLSSoak` 默认运行 3 秒,Linux 长测通过 `GO_OMNI_HTTP2_SOAK_DURATION=30m go test -race ./transport/http2 -run '^TestTLSSoak$'` 启动。
## 目标边界
- HTTP/2 必须作为显式 opt-in 协议,不改变 `omni.New()`、`transport/nethttp` 或 native HTTP/1.1 的默认行为。
- TLS ALPN 只在 HTTP/2 实现通过全部验收后增加 `h2`;当前 native 只宣告 `http/1.1`,误配 `h2` 会在启动时失败。
- Handler、Service、统一响应、requestId、可信代理和业务日志继续复用现有 `httpx.Context` 与 `http.Handler` 边界。
- h2c 只用于本地测试,生产入口使用 TLS + ALPN;不能把明文升级路径默认为公网协议。
## 连接和流的生命周期
1. accept loop 先执行连接上限检查,再执行 TLS 握手;握手受独立超时约束,不能占满连接槽位后无限等待。
2. TLS 协商得到 `h2` 后进入 HTTP/2 connection state;其他 ALPN 直接关闭,不能把 HTTP/2 preface 交给 HTTP/1.1 解析器。
3. 每个 stream 创建独立的 `http.Request` 和取消 context。`RST_STREAM` 只取消当前请求,TCP 断开才取消该连接上的所有请求。
4. `MaxConcurrentRequests` 是所有连接共享的全局请求闸门;`MaxConcurrentStreams` 限制单连接并发流;两者都必须在收到完整请求体前生效。
5. `MaxHeaderBytes` 沿用标准库默认 1 MiB 上限,`MaxBodyBytes` 默认限制请求体为 8 MiB;已声明超限的请求在进入业务 handler 前返回 413,未声明长度的 body 通过受限 reader 读取,避免业务层无意间把整个请求体加载到内存。
6. 服务关闭时停止 accept,发送 GOAWAY 拒绝新流,等待活动流排空;超过 `ShutdownTimeout` 后关闭连接并取消剩余请求。实验 Runner 已覆盖这条顺序。
## 必须可观测的状态
HTTP/2 版本需要在 native `Stats` 之外至少记录:活动 stream、被拒绝 stream、连接级 protocol error、RST_STREAM、GOAWAY 发送次数,以及因流控或并发闸门触发的拒绝。实验 Runner 当前已通过 `ActiveRequests`、`RejectedRequests`、`ProtocolErrors` 和 `GoAwaySent` 暴露活动/拒绝/协议错误/优雅关闭快照;RST_STREAM 的独立计数仍属于进入 native 前的补齐项。计数必须是原子快照,不能在 metrics handler 中锁住连接状态机。
## 进入实现前的验收矩阵
- TLS ALPN:只协商 `h2`,HTTP/1.1 客户端仍由现有 native 路径处理;不支持的 ALPN 在握手前后都不会误入错误解析器。
- 多路复用:一个连接并发至少 128 个 stream,响应和 requestId 不串线,单个慢 stream 不阻塞其他 stream(实验 Runner 已覆盖 128 路同连接 stream)。
- 流控:慢读取、慢写、窗口耗尽和大 body 都能恢复;内存不会随未消费 body 无限增长(实验 Runner 已覆盖 2 MiB 慢读取 body 和请求体上限)。
- 取消:RST_STREAM、客户端断开、服务关闭分别只影响应受影响的请求,并能在 metrics 中看到回收;当前实验 Runner 已覆盖 RST_STREAM 与服务关闭。
- 背压:连接上限、全局 stream 上限、单连接 stream 上限和 header/body 上限均能快速拒绝并自动恢复。
- 代理联调:Nginx/Cloudflare 的 TLS、Keep-Alive、超时、GOAWAY 和优雅发布行为与 HTTP/1.1 回源结果一致。
- 长测:Linux amd64 至少 30 分钟 TLS、多连接、多 stream、慢客户端混合场景;要求 0 协议错误、0 请求串线,连接、stream、goroutine 和 FD 在停止后回收。
只有上述矩阵完成,才把 `h2` 加入 native 的 TLS ALPN,并考虑把 HTTP/2 作为独立版本能力发布。此前生产环境使用 Nginx/Cloudflare 终止 HTTP/2 后以 HTTP/1.1 回源,或使用支持 HTTP/2 的 `transport/nethttp`。