Fiber不能直接用c.Send或c.JSON做反向代理,因其不透传原始请求体和响应流,c.Body()已消耗导致转发Body为空,且会覆盖上游真实状态码与Header;必须用c.Request().Body()或c.Context().RequestBodyStream()流式转发,并手动透传关键Header、清理hop-by-hop头、为每个后端配置独立fasthttp.HostClient并设超时与连接复用参数。

别用 fiber.Default() 启动网关,也别拿 fasthttp.Client 直接转发请求——这两点踩中就大概率线上 502、连接泄漏或响应截断。
为什么不能直接用 Fiber 的 c.Send 或 c.JSON 做反向代理
Fiber 默认不透传原始请求体和响应流,c.Body() 已被读取一次,再调 http.DefaultClient.Do() 时 req.Body 是空的;c.Send() 和 c.JSON() 会强制写入状态码和头,覆盖上游真实响应(比如 401 带 WWW-Authenticate 头、503 带 Retry-After)。
- 必须用
c.Request().Body()获取原始字节流,或用c.Context().RequestBodyStream()做流式转发 - 所有关键 header(
Authorization、Cookie、Content-Type、X-Forwarded-For)要手动拷贝,Fiber 不自动透传 - 大文件或 chunked 响应必须用
io.Copy+responseWriter.Hijack()或fasthttp.StreamResponse,否则内存爆满或卡死
如何正确配置 fasthttp.HostClient 做多后端代理
fasthttp.Client 是全局单例,混用多个域名会导致 Host 头错乱、TLS SNI 冲突、连接池污染;必须为每个后端单独配 fasthttp.HostClient,且 Addr 字段不能带 https://。
-
Addr只填"api.example.com:443",协议由TLSConfig控制;填错会解析失败 - 显式设
DisableKeepAlive: false(默认是false,但不写容易误设为true) -
MaxIdleConnDuration: 30 * time.Second必须设,否则连接无法复用,压测几秒就dial tcp: too many open files - 若后端用自签名证书,需传入定制
TLSConfig,否则握手失败
Director 函数里必须重写 req.URL.Path 和 req.Host
不改 req.URL.Path,后端收不到真实路径(比如网关层 /api/v1/users,后端只认 /users);不设 req.Host,下游服务靠 Host 做多租户路由或证书匹配就会失败。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
-
req.URL.Path = strings.TrimPrefix(req.URL.Path, "/api/v1"):前缀必须和路由注册完全一致,多一个斜杠或大小写错误都会截断失效 -
req.Host = "user-service.default.svc.cluster.local":K8s 场景下必须用 FQDN,不能用 IP 或短名 - 别依赖
req.URL.Host自动同步——它和实际发出的Hostheader 无关联,漏设等于把客户端原始 Host 直接透传
超时、错误透传与 hop-by-hop header 清理怎么做
fasthttp.HostClient 默认没有细粒度超时控制,错误响应不透传,Connection、Keep-Alive 这类 hop-by-hop 头若透传给客户端,会导致连接异常中断。
- 每个
HostClient必须设ReadTimeout和WriteTimeout,建议分别设为10 * time.Second - 错误处理不能用
c.Status(502).SendString(),要捕获err后手动设置c.Set("Content-Type", "application/json")并写标准 error body - 在
fasthttp.StreamResponse的writeHeader回调里,用resp.Header.Del("Connection")、.Del("Keep-Alive")、.Del("Proxy-Authenticate") - WebSocket 流量必须单独拦截,
fasthttp不原生支持 upgrade 协议协商,得用c.Context().Upgrade()手动接管
真实网关最难的不是路由匹配,而是连接生命周期管理——哪个 client 对应哪个 upstream、何时复用、何时关闭、错误时怎么清理资源,这些细节不抠清楚,流量一上来就崩。

















