You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 12:42:44