Go语言需手动构建API网关:用httputil.NewSingleHostReverseProxy配合自定义Director修正路径、Host头及转发头;结合DNS SRV或Consul实现服务发现;必须配置Transport连接池、Server读写超时及proxy.ErrorHandler。
Go 语言本身不提供现成的 API 网关,但用 net/http + 中间件 + 路由分发就能快速构建轻量、可控的微服务网关——关键不在“有没有”,而在“怎么转”和“转得稳不稳”。
用 http.ServeMux 做基础路由分发容易踩哪些坑
直接用默认 http.ServeMux 分发请求到不同微服务(如 /user/* → user-svc,/order/* → order-svc)看似简单,但实际会遇到:
- 路径前缀被截断后,下游服务收不到原始路径(比如
/user/v1/profile转给 user-svc 时变成/v1/profile,而 user-svc 期望的是/user/v1/profile) - 无法透传 Host 头,导致下游服务生成的绝对 URL 错误(例如重定向地址写成
http://localhost:8081/...) - 不支持动态更新路由规则,每次改路径都要重启网关
解决办法是绕过 http.ServeMux 的自动路径裁剪,改用 http.NewServeMux() 配合手动 http.StripPrefix + httputil.NewSingleHostReverseProxy,并显式设置 Director 函数修正 Request.URL 和 Host 头。
httputil.NewSingleHostReverseProxy 必须重写的 Director 函数
这是反向代理的核心控制点,不重写就等于裸转发,多数业务场景会失败。典型修正项包括:
- 把原始请求路径完整复制过去,避免路径丢失:
req.URL.Path = oldPath - 显式设置
req.Host = proxyURL.Host,防止下游依赖 Host 头做租户识别或 CORS 判断 - 保留原始
X-Forwarded-For并追加客户端 IP:req.Header.Set("X-Forwarded-For", clientIP) - 清除可能引发循环的跳转头:
req.Header.Del("Connection")、req.Header.Del("Keep-Alive")
示例片段: