基于Go开发支持REST与gRPC的API网关实现技术咨询
Go 实现支持REST与原生gRPC转发的简易API网关
针对你的场景,我们可以基于Go标准库快速搭建一个同时支持HTTP/1.1(REST)和HTTP/2(原生gRPC)的API网关,核心是利用net/http和httputil实现路由转发,无需依赖grpc-gateway这类JSON转换工具。
核心逻辑
gRPC本身基于HTTP/2协议,Go标准库从1.6版本开始原生支持HTTP/2,因此网关可以直接通过标准库搭建服务器,根据请求路径和协议特性,将请求转发到对应的后端服务:
- 路径前缀
/articles的请求转发到REST类型的ArticleService - 路径前缀
/user的请求转发到原生gRPC的UserService(保留protobuf格式)
具体实现步骤
1. 依赖导入
仅需Go标准库和gRPC基础包,无需额外重型框架:
import ( "net/http" "net/http/httputil" "net/url" "strings" )
2. 配置后端服务地址
先定义两个服务的目标地址,初始化反向代理实例:
// 配置ArticleService的REST服务地址 articleTarget, _ := url.Parse("http://localhost:8081") articleProxy := httputil.NewSingleHostReverseProxy(articleTarget) // 配置UserService的gRPC服务地址 userTarget, _ := url.Parse("grpc://localhost:8082") userProxy := httputil.NewSingleHostReverseProxy(userTarget)
3. 自定义路由转发逻辑
编写核心Handler,根据路径区分请求类型,处理gRPC的路径格式要求:
func gatewayHandler(w http.ResponseWriter, r *http.Request) { // 转发/articles前缀的REST请求 if strings.HasPrefix(r.URL.Path, "/articles") { r.URL.Host = articleTarget.Host r.URL.Scheme = articleTarget.Scheme articleProxy.ServeHTTP(w, r) return } // 转发/user前缀的gRPC请求 if strings.HasPrefix(r.URL.Path, "/user") { // gRPC标准路径格式为 /package.Service/Method,需根据你的proto定义调整 // 示例:将请求路径/user/GetUser转换为/user.UserService/GetUser adjustedPath := strings.Replace(r.URL.Path, "/user", "/user.UserService", 1) r.URL.Path = adjustedPath r.URL.Host = userTarget.Host r.URL.Scheme = userTarget.Scheme // 确保保留gRPC的Content-Type头 w.Header().Set("Content-Type", "application/grpc") userProxy.ServeHTTP(w, r) return } // 处理未知路径请求 http.NotFound(w, r) }
4. 启动支持HTTP/2的服务器
Go的http.Server默认在TLS环境下启用HTTP/2,开发环境可强制开启HTTP/2(无需TLS,Go 1.20+支持):
func main() { server := &http.Server{ Addr: ":8080", Handler: http.HandlerFunc(gatewayHandler), // 开发环境强制启用HTTP/2 ForceHTTP2: true, } if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { panic(err) } }
关键注意事项
- gRPC路径匹配:必须严格对应你的UserService Protobuf定义,标准gRPC路径格式为
/package名.Service名/方法名,比如proto包为user、服务名为UserService,则GetUser方法的路径是/user.UserService/GetUser - 生产环境配置:生产环境建议使用TLS证书,因为多数客户端默认仅在TLS连接上使用HTTP/2
- 请求头保留:
httputil.ReverseProxy默认会保留所有请求头,包括gRPC依赖的grpc-timeout等特殊头,无需额外处理 - 错误扩展:可以给反向代理添加自定义错误处理逻辑,比如后端服务不可用时返回特定提示
进阶扩展方向
如果后续需要添加负载均衡、认证、限流等功能,可考虑:
- 使用
grpc-ecosystem/go-grpc-middleware扩展gRPC中间件能力 - 基于
mholt/caddy快速扩展网关功能(需自定义配置)
内容的提问来源于stack exchange,提问作者hskris
相关产品推荐
相关产品推荐

