跳到主要内容

API 网关

问题

微服务为什么需要 API 网关?Go 中怎么实现?

答案

网关职责

职责说明
路由分发根据 URL 转发到对应微服务
认证鉴权统一 JWT 验证,不用每个服务重复实现
限流保护后端,令牌桶/滑动窗口
灰度发布按用户/流量比例路由到新版本
协议转换外部 HTTP → 内部 gRPC
聚合多个服务结果合并返回

Go 实现简易网关

func main() {
r := gin.Default()
r.Use(AuthMiddleware(), RateLimitMiddleware())

// 反向代理
r.Any("/api/users/*path", reverseProxy("http://user-service:8080"))
r.Any("/api/orders/*path", reverseProxy("http://order-service:8080"))

r.Run(":9000")
}

func reverseProxy(target string) gin.HandlerFunc {
remote, _ := url.Parse(target)
proxy := httputil.NewSingleHostReverseProxy(remote)

return func(c *gin.Context) {
// 传递 TraceID
c.Request.Header.Set("X-Request-ID", c.GetString("requestID"))
proxy.ServeHTTP(c.Writer, c.Request)
}
}

主流网关方案

方案语言特点
KongLua/Go插件丰富、社区大
APISIXLua动态路由、高性能
自研 Go 网关Go灵活定制
EnvoyC++Service Mesh 数据面
gRPC-GatewayGogRPC ↔ REST 转换

gRPC-Gateway

自动将 RESTful HTTP 请求转换为 gRPC 调用:

// 在 proto 文件中定义 HTTP 映射
service UserService {
rpc GetUser(GetUserRequest) returns (User) {
option (google.api.http) = {
get: "/api/v1/users/{id}"
};
}
}
客户端: GET /api/v1/users/123
↓ gRPC-Gateway 自动转换
gRPC: UserService.GetUser({id: 123})

常见面试问题

Q1: 网关和 Nginx 反向代理的区别?

答案

  • Nginx:通用反向代理,配置静态,重新加载需 reload
  • API 网关:专为微服务设计,支持动态路由、鉴权、限流、服务发现、协议转换

网关 = Nginx + 更多微服务能力。小规模可以用 Nginx,微服务多了建议用 Kong/APISIX。

Q2: BFF 和 API 网关的区别?

答案

  • API 网关:通用的基础设施层(路由、鉴权、限流)
  • BFF(Backend For Frontend):面向特定客户端的聚合层(移动端 BFF、Web BFF)

通常架构:客户端 → 网关 → BFF → 微服务。

相关链接