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)
}
}
主流网关方案
| 方案 | 语言 | 特点 |
|---|---|---|
| Kong | Lua/Go | 插件丰富、社区大 |
| APISIX | Lua | 动态路由、高性能 |
| 自研 Go 网关 | Go | 灵活定制 |
| Envoy | C++ | Service Mesh 数据面 |
| gRPC-Gateway | Go | gRPC ↔ 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 → 微服务。