feat: support native streaming responses

This commit is contained in:
2026-09-21 04:02:04 +08:00
parent 694374fde8
commit 62b0f09546
6 changed files with 252 additions and 9 deletions

View File

@@ -16,6 +16,8 @@ registerRoutes(application) // 与 omni.New() 复用同一份业务注册代码
`transport/native` 是第一版自研 HTTP/1.1 服务端:它自己管理 TCP listener、连接、Keep-Alive、请求解析、响应写回和优雅关闭,再把请求交给现有 `http.Handler`。请求体支持 `Content-Length` 和 chunked,并统一受 `MaxBodyBytes` 限制;其他传输编码会被拒绝。它仍使用标准 `http.Request` / `http.ResponseWriter` 作为业务桥接,因此不会影响现有 Handler / Service。
业务 Handler 需要流式返回时可以断言 `http.Flusher` 并调用 `Flush()`;HTTP/1.1 会自动使用 chunked 响应,普通未 Flush 的响应仍自动生成 `Content-Length`。HTTP/1.0 没有 chunked framing,会退回到写完后关闭连接。
服务端不是把连接交给一个全局串行 worker,而是每条连接独立处理请求;Keep-Alive 负责复用客户端连接,`Server` 内部的 `sync.Pool` 负责复用小型 Reader、响应对象和连接状态。Reader 默认只有 4 KiB,需要处理大请求头时按需增长。需要保护内存上限时,可以设置 `MaxConnections` 和 `MaxConcurrentRequests`;超出连接上限的连接会被关闭,超出请求并发上限的请求返回 503,不会无限排队。
这个设计借鉴了 Nginx 的资源边界,但没有照搬它的进程模型:Nginx 用少量 worker 进程和事件机制管理大量连接,并用 `worker_connections` 限制每个 worker 的同时连接数;Go runtime 自己已经用 epoll / kqueue 等网络轮询器唤醒阻塞的 goroutine,因此 native 采用“accept loop + 每连接轻量 goroutine + 请求并发闸门”的等价实现。这样业务 Handler 可以继续执行同步代码,慢请求不会阻塞其他连接;只有在真实压测证明 goroutine 调度或协议状态机成为瓶颈时,才需要继续下沉为手写事件循环。