2023 年底我们做 API 网关选型,在 Kong / APISIX / Spring Cloud Gateway / Envoy / Higress 五个候选里折腾了三个月,最终选 APISIX。本文把当时的对比、压测数据、踩坑过程整理出来,给在做类似选型的团队参考。结论先说:没有银弹,选型看团队栈和需求边界,不要看 GitHub star。
需求清单
业务要求:
- 日均 5 亿请求,峰值 20w QPS
- 路由数 500+(50 个微服务,每个 10 条左右路由)
- 多协议:HTTP/HTTPS、gRPC、WebSocket
- 鉴权:OAuth2 / JWT / API Key 三种
- 限流:基于 IP / 用户 / 接口三个维度
- 灰度发布:按 header / 流量比例 / 灰度名单
- 可观测:Prometheus + Skywalking trace
- 配置热更新(改路由不能重启)
- 团队栈:Java 为主,运维有 Python 经验
- 不希望搞 Lua(运维不会)
五个候选简评
候选 内核 配置 插件生态 性能 (QPS) 上手难度
=============================================================================
Kong OpenResty(Lua) declarative 强 30k 中
APISIX OpenResty(Lua) etcd 强 40k+ 中
SCG (Spring) Netty(Java) YAML 中 15k 低(Java)
Envoy C++ xDS protobuf 中 50k+ 高
Higress (基于 Envoy) C++ CRD 强 50k+ 中
压测对比
压测环境:4C8G × 3 节点,wrk -t 8 -c 200,空插件
延迟 p99(ms):
空载 JWT 鉴权 JWT+限流+trace
Kong 18 42 75
APISIX 12 28 55
SCG 28 85 150
Envoy 8 22 48
Higress 9 23 50
QPS:
空载 JWT 鉴权 JWT+限流+trace
Kong 32000 18000 9500
APISIX 42000 24000 13000
SCG 15500 8500 4200
Envoy 51000 27000 14500
Higress 49000 26000 14000
资源占用(满负载):
CPU 内存
Kong 75% 220MB
APISIX 65% 180MB
SCG 90% 650MB(JVM)
Envoy 55% 130MB
Higress 58% 145MB
路由配置对比
# Kong 声明式(declarative)
_format_version: "3.0"
services:
- name: order-service
url: http://order-service.default.svc:8080
routes:
- name: order-route
paths: ["/api/order"]
plugins:
- name: jwt
- name: rate-limiting
config:
minute: 100
policy: redis
# APISIX(etcd 存储,可 yaml/json 导入)
routes:
-
uri: /api/order/*
upstream:
type: roundrobin
nodes:
"order-service.default.svc:8080": 1
plugins:
jwt-auth:
key: order-key
limit-count:
count: 100
time_window: 60
policy: redis-cluster
redis_cluster_nodes:
- "redis-0:7000"
- "redis-1:7000"
# Spring Cloud Gateway
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
# Envoy(xDS)— 略复杂,通常用控制面如 Istio / Higress 生成
# Higress CRD(K8s)
apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
name: order-route
spec:
routeName: order
match:
uri:
prefix: /api/order
destination:
host: order-service.default.svc
filters:
- name: jwt
- name: rate-limit
config:
rules: [{ limit: 100, window: 60s, key: header.x-user-id }]
插件 / 扩展能力
Kong:
- 官方 100+ 插件,生态成熟
- 自定义插件用 Lua
- 企业版有 GUI(开源版无)
APISIX:
- 80+ 内置插件
- 自定义可用 Lua,但更支持 Wasm
- 提供 Java/Go/Python 的 Plugin Runner(JVM 进程外通信)
- GUI(APISIX Dashboard)开源免费
SCG:
- 跟 Spring 生态深度结合
- 自定义 GatewayFilter 用 Java(团队友好)
- 但生态不如 Kong/APISIX 丰富
Envoy:
- 插件用 C++ 或 Wasm
- 配置全用 protobuf 写,门槛高
- 通常配合控制面(Istio / Higress)用
Higress:
- 基于 Envoy + Istio,沉淀阿里多年实战
- 自定义插件 Go/Wasm
- K8s 原生,CRD 配置
- 比 Istio 轻,网关场景专用
为什么最终选 APISIX
1. 性能强:同等硬件 QPS 比 Kong 高 30%,延迟低 30%
2. 配置存 etcd,改路由秒级生效(Kong 也行,SCG 要刷新)
3. APISIX Dashboard 开源免费,Kong GUI 要钱
4. Plugin Runner 支持 Java(团队栈友好)
5. 中国社区活跃,问题响应快
6. 文档中文版本完整
7. 基于 etcd 不需要数据库(Kong 要 Postgres 或 Cassandra)
但有一些坑:
- Lua 调试不友好,内置插件出问题排查难
- etcd 一旦挂,网关不能更新配置(运行不影响)
- Dashboard 历史版本 bug 多,现在稳定了
- 文档质量参差,有些插件示例缺失
APISIX 部署
# K8s 部署(Helm)
$ helm repo add apisix https://charts.apiseven.com
$ helm repo update
$ helm install apisix apisix/apisix \
--namespace apisix --create-namespace \
--set gateway.type=LoadBalancer \
--set ingress-controller.enabled=true \
--set etcd.enabled=true \
--set etcd.replicaCount=3 \
--set dashboard.enabled=true
# 验证
$ kubectl -n apisix get pods
NAME READY STATUS RESTARTS
apisix-7d4f8b6cdf-x2k4t 1/1 Running 0
apisix-7d4f8b6cdf-9pj2m 1/1 Running 0
apisix-7d4f8b6cdf-z8nv3 1/1 Running 0
apisix-dashboard-6c7b9c8b-q3pwl 1/1 Running 0
apisix-etcd-0 1/1 Running 0
apisix-etcd-1 1/1 Running 0
apisix-etcd-2 1/1 Running 0
# Admin API 添加路由
$ curl http://apisix-admin:9180/apisix/admin/routes/1 \
-H "X-API-KEY: xxx" -X PUT -d '
{
"uri": "/api/order/*",
"name": "order",
"upstream": {
"type": "roundrobin",
"nodes": {"order-service.default.svc:8080": 1}
},
"plugins": {
"jwt-auth": {},
"limit-count": {
"count": 1000,
"time_window": 60,
"key": "remote_addr",
"policy": "redis-cluster"
},
"prometheus": {},
"skywalking": {"sample_ratio": 0.1}
}
}'
自定义插件(Java Plugin Runner)
// 团队不熟 Lua,自定义插件用 Java + apisix-java-plugin-runner
@Component
public class UserContextEnrichPlugin implements PluginFilter {
@Override
public String name() {
return "user-context-enrich";
}
@Override
public void filter(PluginRequest request, PluginResponse response, PluginFilterChain chain) {
// 从 JWT 解析用户信息,写入下游 header
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
try {
Claims claims = JwtUtil.parse(token.substring(7));
request.setHeader("X-User-Id", claims.getSubject());
request.setHeader("X-User-Tenant", claims.get("tenant", String.class));
request.setHeader("X-User-Roles", String.join(",", claims.get("roles", List.class)));
} catch (Exception e) {
response.setStatusCode(401);
response.setBody("{\"error\":\"invalid token\"}");
return;
}
}
chain.filter(request, response);
}
}
// 启动:
// java -jar apisix-java-plugin-runner.jar
// APISIX 通过 unix socket 调用 java runner
限流配置(三维度)
# IP 维度限流(防爬虫)
plugins:
limit-conn:
conn: 100
burst: 50
default_conn_delay: 0.1
key_type: var
key: remote_addr
rejected_code: 429
# 用户维度限流(VIP / 普通)
plugins:
limit-count:
count: 1000
time_window: 60
key_type: var
key: http_x_user_id
policy: redis-cluster
redis_cluster_nodes:
- "redis-cluster:6379"
# 接口维度(秒杀防刷)
plugins:
limit-req:
rate: 100 # 每秒 100 个
burst: 50 # 允许突发 50
key_type: var
key: uri
灰度发布
# traffic-split 插件
plugins:
traffic-split:
rules:
- match:
- vars:
- ["http_x_canary", "==", "true"] # header 灰度
weighted_upstreams:
- upstream_id: "order-canary"
weight: 1
- weighted_upstreams:
- upstream_id: "order-stable"
weight: 95
- upstream_id: "order-canary"
weight: 5 # 5% 流量灰度
监控与可观测
# Prometheus 插件
plugins:
prometheus:
prefer_name: true
# Skywalking trace
plugins:
skywalking:
sample_ratio: 0.1 # 10% 采样
endpoint_addr: http://skywalking-oap:12800
# 访问日志(异步写 Kafka)
plugins:
kafka-logger:
broker_list:
- "kafka-1:9092"
- "kafka-2:9092"
kafka_topic: "apisix-access-log"
timeout: 3
batch_max_size: 100
inactive_timeout: 5
选型决策树
团队是 Java 栈,简单需求 → SCG
团队是 Java 栈,需要高性能 + 复杂插件 → APISIX + Java Plugin Runner
有 OpenResty / Lua 经验 → Kong 或 APISIX
全员云原生 + K8s 重度用户 → Higress 或 Envoy
追求极致性能 → Envoy
要图形化管理 + 多租户 → Kong Enterprise(付费)或 APISIX Dashboard
不想自己运维 → 云厂商 API 网关(腾讯 API 网关 / 阿里 EDAS / AWS API Gateway)
避坑清单
- 不要直接看 GitHub star,要看实际场景的性能压测
- 团队熟悉的栈最重要,Java 团队选 Lua 网关有学习成本
- 插件可用性 ≠ 插件好用,要看文档完整度和社区活跃度
- 限流别只用网关,业务侧也要兜底
- JWT 验证放网关,签发放业务,撤销机制要想清楚
- etcd / Redis 一定要 HA,否则网关瘫
- Dashboard 不要暴露公网,加双因素
- 升级前在测试环境跑全量 case,Lua 插件兼容性偶尔会断
- 路由数量上千的话压测路由匹配性能,前缀树 vs hash 差别大
- 不要在网关写业务逻辑,网关是路由 + 横切关注点
三个月对比的反思
选型这事最忌讳"看大家用什么"。Kong 在国外强,APISIX 在国内强,SCG 在 Java 团队香,Envoy 在云原生圈热,各有自己的护城河。最终我们选 APISIX 是因为性能 + 配置存 etcd + Java Plugin Runner + 中文社区 + 免费 Dashboard 五点叠加,不是单一指标决定。如果你的团队是纯 Spring 生态,SCG 反而更顺手。建议每个候选拿真实业务流量压测一周再决定,纸面参数和实际跑起来差别大。
—— 别看了 · 2026