# api-gateway **Repository Path**: solidify-the-foundation/api-gateway ## Basic Information - **Project Name**: api-gateway - **Description**: No description available - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-17 - **Last Updated**: 2026-06-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 高性能 API 网关 (Go) 一个基于 **Go + fasthttp** 实现的生产级骨架式 API 网关,强调 **吞吐量** 与 **可观测性**,可作为微服务南北向流量入口的起点。 > 配置 → `configs/config.yaml`;启动 → `go run ./cmd/gateway`;一键体验 → `docker-compose up -d` > **设计文档** → 见 [`docs/`](./docs/) 目录,按 01~12 编号循序渐进介绍每一个技术决策、对比方案与原因。 --- ## 1. 目录结构 ```text api-gateway/ ├── cmd/ │ ├── gateway/ # 主程序入口 │ └── upstream-demo/ # 演示用上游服务(多端口启动模拟多实例) ├── configs/config.yaml # 路由、限流、缓存、鉴权、observability 全部在此 ├── internal/ │ ├── balancer/ # 负载均衡:RR / Random / LeastConn / 一致性哈希 │ ├── config/ # viper 配置加载 + 环境变量覆盖 │ ├── discovery/ # 服务发现:static / etcd │ ├── logger/ # zap 结构化日志 │ ├── middleware/ # 限流、JWT、缓存、熔断、Metrics、AccessLog │ ├── proxy/ # HTTP 反向代理 + WebSocket 代理 │ └── server/ # 装配总入口(fasthttp + admin + ws) ├── deploy/prometheus.yml ├── scripts/bench.sh # hey 压测脚本 ├── Dockerfile └── docker-compose.yml # gateway + redis + etcd + prometheus + grafana ``` ## 2. 快速开始 ### 方式 A:本机运行(最快) ```bash # 1. 拉依赖(如果走代理,建议先设置) export GOPROXY=https://goproxy.cn,direct export GOSUMDB=off go mod tidy # 2. 启两个上游 demo go run ./cmd/upstream-demo -addr :18081 -name up-1 & go run ./cmd/upstream-demo -addr :18082 -name up-2 & # 3. 启网关(默认监听 8080、ws 8081、admin 9090) go run ./cmd/gateway --config configs/config.yaml # 4. 验证: curl -s http://127.0.0.1:8080/api/user/ping curl -s http://127.0.0.1:9090/metrics | head ``` ### 方式 B:Docker Compose 一键起栈 ```bash docker-compose up -d --build open http://127.0.0.1:3000 # Grafana (admin/admin) open http://127.0.0.1:9091/targets # Prometheus ``` ### 方式 C:压测 ```bash brew install hey # 或:go install github.com/rakyll/hey@latest ./scripts/bench.sh http://127.0.0.1:8080/api/user/ping ``` --- ## 3. 核心技术要点 ### 3.1 网络层 —— 为什么选 fasthttp - 标准库 `net/http` 每请求一个 goroutine + 频繁的小对象分配,在 5w+ QPS 下 GC 压力大。 - `valyala/fasthttp` 复用 `RequestCtx`、零拷贝 byte slice、自带连接复用与 worker pool,在相同硬件下吞吐通常提升 **3~10 倍**。 - `HostClient` 为每个上游维持独立连接池(`MaxConns=4096`、`MaxIdleConnDuration=90s`),消除频繁握手。 - 关闭 header 名规范化 (`DisableHeaderNamesNormalizing`)、加大 `ReadBufferSize/WriteBufferSize` 进一步降低 syscall。 ### 3.2 路由 & 反向代理 - 使用 `fasthttp/router`:基于 radix tree 的零分配路由匹配,复杂度 O(k)。 - 自研 `internal/proxy`:支持 `strip_prefix`、保留 `X-Forwarded-For/X-Real-IP`、按 path 做一致性哈希 key。 - WebSocket 单独走 `net/http + nhooyr.io/websocket`:fasthttp 不原生支持流式升级,避免把长连接和短连接耦合在同一服务器。 ### 3.3 负载均衡 四种策略可在路由维度独立配置: | 策略 | 适用场景 | |------|----------| | `round_robin` | 默认,无状态服务 | | `random` | 简单、避免同步成本 | | `least_conn` | 长尾延迟较多的下游 | | `consistent_hash` | 缓存亲和、会话保持,扩缩容抖动小 | ### 3.4 限流(双层) - **全局令牌桶**:基于 `golang.org/x/time/rate`,是任何流量进入路由前的总闸门。 - **路由级 + 客户端 IP 维度**:用 `sync.Map` 分桶 + 后台 GC 清理过期 entry,避免锁竞争与内存膨胀。 - 触发限流时返回 `429 Too Many Requests`,并设置 `Retry-After: 1`。 ### 3.5 鉴权 - HS256 JWT(与上游共享 secret,性能 >> RSA)。 - 配置级 `skip_paths` 支持 `/api/public/*` 通配。 - 校验通过后写入 `X-User-Id`,下游直接消费,无需重复解析 token。 - 可平滑替换为 OAuth2 / JWKS(缓存远端公钥)。 ### 3.6 缓存(两级) - L1:本地 LRU(演示版简化驱逐,生产建议替换为 `hashicorp/golang-lru/v2`)。 - L2:Redis(连接池 256,最小空闲 32),失败回源。 - 仅缓存幂等方法(默认 GET),Key 由 `method + URI` 组成;可扩展加 `X-User-Id` 实现"按用户缓存"。 - 命中带回 `X-Cache: LOCAL|REDIS` 头便于线上排障。 ### 3.7 熔断 - 实现 `Closed → Open → HalfOpen` 三态机:错误率 > 阈值且样本足够 → 熔断;OpenTimeout 后试探放行一次。 - 防止上游故障时压垮上游 & 网关连接池雪崩。 ### 3.8 服务发现 & 动态路由 - 抽象 `ServiceWatcher` 接口;提供 `static` 与 `etcd` 两种实现。 - etcd 启用后自动 `Watch` 前缀,上游变更 → 调用 `Balancer.Update`,**零停机切换**。 - 演进方向:支持 Consul / Nacos / k8s endpoints,统一以同一接口落地。 ### 3.9 可观测性 - **Metrics**:`gateway_requests_total{route,method,status}`、`gateway_request_duration_seconds`、`gateway_inflight_requests`,全部按路由维度,状态码归类为 `2xx/4xx/5xx` 控制基数。 - **结构化日志**:zap JSON 输出,每条访问日志自动注入 `X-Request-Id`(透传给上游做全链路追踪)。 - **链路追踪**:预留 `OTLP gRPC` 接入位,可对接 Jaeger / Tempo。 - 独立 admin 端口(9090)暴露 `/metrics`、`/health`,与业务端口隔离,避免外网误访问。 ### 3.10 协议扩展 - HTTP/1.1、HTTP/2(fasthttp v1.55+ 实验支持)。 - WebSocket:全双工双向 `io.Copy`,单独 server。 - gRPC:建议通过 `grpc-go` + `cmux` 复用端口或直接走 envoy/grpc-proxy;为简单计当前不在主路径内。 ### 3.11 优雅停机 - 监听 `SIGINT/SIGTERM`,按顺序停止 admin server → ws server → 主 fasthttp server → 关 Redis/etcd 连接。 - `shutdown_timeout` 限制最长等待,避免 K8s 滚动更新被卡住。 ### 3.12 配置中心 - viper 支持文件 + 环境变量覆盖(前缀 `GATEWAY_`),例如: ```bash GATEWAY_CACHE_REDIS_ADDR=10.0.0.5:6379 ./gateway ``` - 后续可挂接 etcd/Nacos 实现热更新(监听 → 重建 router)。 ### 3.13 容器化 - 多阶段构建 + `distroless/nonroot`:最终镜像 < 20MB、无 shell、无 root,安全又快。 - 通过 BuildKit cache mount 加速二次构建。 --- ## 4. 压测建议参数(macOS / Linux) ```bash # 内核 sysctl -w net.ipv4.tcp_tw_reuse=1 ulimit -n 1048576 # 应用 GOGC=300 # 提升吞吐,降低 GC 频率 GOMAXPROCS=$(nproc) GATEWAY_SERVER_ADDR=:8080 ``` 参考结果(M2 Pro,单实例,2 个本机 upstream): | 场景 | QPS | P99 | |------|----:|----:| | 直连 upstream | ~140k | 2ms | | 经网关(含 metrics + 日志) | ~95k | 4ms | | 网关 + JWT + 限流 | ~70k | 6ms | | 网关 + 本地缓存命中 | ~180k | 1.5ms | > 数字与硬件、调优、middleware 数量强相关,仅作量级参考。 --- ## 5. 路线图(可选演进) - [ ] 动态路由热更新 HTTP API(POST /admin/routes) - [ ] OpenTelemetry trace 串联上游 - [ ] mTLS 终止 & SNI 路由 - [ ] WAF 插件(基于 modsecurity-go 或自研规则) - [ ] 多租户配额、按 API Key 计费 - [ ] gRPC-Web → gRPC 协议转换 - [ ] 灰度发布(按 header / weight 分流) --- ## 6. License MIT