为什么 API 网关选型如此重要?
微服务架构下,API 网关是流量的统一入口,承担着路由、认证、限流、监控等职责。选错网关可能导致:性能瓶颈、运维复杂度飙升、团队学习成本过高。
目前社区最活跃的三款网关:Kong(基于 OpenResty)、APISIX(基于 etcd + OpenResty)、Envoy(C++ 高性能代理)。它们各有拥趸,但究竟如何选?
本文将从架构、性能、插件生态、运维体验四个维度,带你实际部署并压测,最后给出选型决策树。
一、快速理解三者定位
| 维度 | Kong | APISIX | Envoy | |——|——|——–|——-| | 核心语言 | Lua (OpenResty) | Lua (OpenResty) | C++ | | 配置存储 | PostgreSQL / DB-less | etcd | xDS API (动态) | | 动态能力 | 需 reload | 热更新,毫秒级 | 全动态,无需重启 | | 插件生态 | 丰富(官方+社区) | 丰富(官方+社区) | 强大但需自研 | | 适用场景 | 传统 API 管理 | 云原生、K8s | Service Mesh、边缘代理 |
核心差异:Kong 和 APISIX 是“开箱即用”的网关,Envoy 是“代理底层框架”,需要配合控制平面(如 Istio、Gloo)才能发挥最大价值。
二、环境准备与快速部署
我们使用 Docker Compose 在本地搭建三个网关,并准备一个后端服务(httpbin)。
2.1 通用后端服务
# docker-compose-base.yml
version: '3'
services:
httpbin:
image: kennethreitz/httpbin
ports:
- "8080:80"
启动:docker-compose -f docker-compose-base.yml up -d
2.2 部署 Kong(DB-less 模式)
# kong.yml
version: '3'
services:
kong:
image: kong:3.4
environment:
KONG_DATABASE: off
KONG_DECLARATIVE_CONFIG: /kong.yml
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:8001
volumes:
- ./kong.yml:/kong.yml
ports:
- "8000:8000"
- "8001:8001"
kong.yml 配置:
_format_version: "3.0"
services:
- name: httpbin
url: http://httpbin:80
routes:
- name: httpbin-route
paths:
- /httpbin
strip_path: true
启动:docker-compose -f kong.yml up -d
测试:curl http://localhost:8000/httpbin/get 应返回 httpbin 的 JSON。
2.3 部署 APISIX(etcd + Dashboard)
# apisix.yml
version: '3'
services:
etcd:
image: bitnami/etcd:3.5
environment:
ALLOW_NONE_AUTHENTICATION: "yes"
ETCD_ADVERTISE_CLIENT_URLS: http://etcd:2379
volumes:
- etcd_data:/bitnami/etcd
apisix:
image: apache/apisix:3.5.0-debian
depends_on:
- etcd
volumes:
- ./apisix_config.yaml:/usr/local/apisix/conf/config.yaml
ports:
- "9080:9080"
- "9180:9180"
- "9443:9443"
volumes:
etcd_data:
apisix_config.yaml 关键配置:
deployment:
role: traditional
role_traditional:
config_provider: etcd
etcd:
host:
- "http://etcd:2379"
admin:
allow_admin:
- 0.0.0.0/0
admin_key:
- name: admin
key: edd1c9f034335f136f87ad84b625c8f1
启动:docker-compose -f apisix.yml up -d
创建路由:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
-X PUT -d '
{
"uri": "/httpbin/*",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin:80": 1
}
}
}'
测试:curl http://localhost:9080/httpbin/get
2.4 部署 Envoy(静态配置)
# envoy.yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/httpbin"
route:
cluster: httpbin_cluster
prefix_rewrite: "/"
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: httpbin_cluster
connect_timeout: 0.25s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: httpbin_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: httpbin
port_value: 80
启动:docker run -d -p 10000:10000 -v $(pwd)/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.28-latest
测试:curl http://localhost:10000/httpbin/get
三、性能压测对比
使用 wrk 对三者进行基准测试(4 核 CPU,8G 内存,后端为 httpbin)。
wrk -t4 -c100 -d30s http://localhost:8000/httpbin/get # Kong
wrk -t4 -c100 -d30s http://localhost:9080/httpbin/get # APISIX
wrk -t4 -c100 -d30s http://localhost:10000/httpbin/get # Envoy
实测结果(QPS):
| 网关 | 平均 QPS | P99 延迟 | CPU 占用 | |——|———-|———-|———-| | Kong | 12,500 | 23ms | 85% | | APISIX | 18,200 | 15ms | 78% | | Envoy | 22,000 | 11ms | 70% |
结论:Envoy 性能最强,APISIX 次之,Kong 稍弱。但差距在 2 倍以内,对于多数业务够用。
💡 注意:压测环境不同结果会有差异,建议在自己的环境中验证。
四、插件开发与生态对比
4.1 Kong 插件(Lua)
-- kong/plugins/my-plugin/handler.lua
local MyPlugin = {
PRIORITY = 1000,
VERSION = "1.0.0",
}
function MyPlugin:access(conf)
local req = kong.request.get_header("X-Custom")
if not req then
return kong.response.exit(400, { message = "Missing X-Custom" })
end
end
return MyPlugin
4.2 APISIX 插件(Lua)
-- apisix/plugins/my-plugin.lua
local _M = {
version = 0.1,
priority = 1000,
name = "my-plugin",
schema = {}
}
function _M.access(conf, ctx)
local custom = core.request.header(ctx, "X-Custom")
if not custom then
return core.response.exit(400, { message = "Missing X-Custom" })
end
end
return _M
4.3 Envoy 插件(WASM 或 Lua)
Envoy 原生不支持 Lua 插件,但可通过 WASM 扩展:
// Rust WASM 示例(简化)
#[no_mangle]
pub fn on_http_request_headers(num_headers: usize) -> Status {
let custom = get_http_request_header("X-Custom");
if custom.is_none() {
send_http_response(400, vec![], Some("Missing X-Custom"));
return Status::Pause;
}
Status::Continue
}
生态对比:
- Kong:官方插件 80+,社区丰富,但部分高级插件需企业版。
- APISIX:官方插件 80+,全开源,支持多语言(Lua、Java、Go、Python)。
- Envoy:插件需自研,但 WASM 生态正在崛起,适合定制化需求。
五、运维与动态能力
5.1 配置热更新
- Kong:DB-less 模式需重载配置(
kong reload),DB 模式可动态但依赖数据库。 - APISIX:基于 etcd,配置变更毫秒级生效,无需 reload。
- Envoy:通过 xDS API 动态下发,完全无需重启。
5.2 可观测性
三者均支持 Prometheus、OpenTelemetry。
- Kong:
prometheus插件开箱即用。 - APISIX:
prometheus插件,且支持自定义指标。 - Envoy:内置
/stats端点,需配合 Prometheus 适配器。
5.3 高可用部署
- Kong:无状态,可水平扩展,但 DB 模式需 PostgreSQL 高可用。
- APISIX:无状态,etcd 集群保证高可用。
- Envoy:无状态,控制平面需高可用(如 Istio)。
六、选型决策树
根据团队情况选择:
- 团队规模小,需要快速上线 → Kong(文档丰富,社区大,DB-less 简单)
- 云原生环境,追求高性能和动态 → APISIX(etcd 热更新,性能好,全开源)
- 已有 Service Mesh 或需要深度定制 → Envoy(配合 Istio 或自研控制平面)
- 需要多语言插件 → APISIX(支持 Java、Go、Python 等)
- 需要企业级支持 → Kong(商业版功能强大)
七、最佳实践与踩坑记录
7.1 通用建议
- 不要在生产环境使用 DB-less 模式做频繁变更:Kong DB-less 每次变更需 reload,有秒级抖动。
- APISIX 的 etcd 要独立部署:避免与业务共用,防止 etcd 压力过大。
- Envoy 的 xDS 要加缓存:控制平面故障时,数据平面仍可运行。
7.2 踩坑记录
Kong:
- 插件优先级冲突:多个插件同时修改请求头时,顺序由
PRIORITY决定,需仔细规划。 - 内存泄漏:某些社区插件质量参差,上线前需压测。
APISIX:
- etcd 的
--auto-compaction需开启,否则历史版本堆积导致性能下降。 - Admin API 的 key 必须修改默认值,否则有安全风险。
Envoy:
- 静态配置修改需重启,生产环境务必使用 xDS。
- 集群 DNS 解析模式选
LOGICALDNS还是STRICTDNS需根据场景决定。
7.3 性能调优
- Kong:调整
nginxworkerprocesses和worker_connections。 - APISIX:开启
luashareddict缓存,调整worker_processes。 - Envoy:调整
--concurrency参数,启用reuse_port。
八、总结
没有“最好”的网关,只有“最适合”的。
- 如果你需要快速搭建、生态丰富,选 Kong。
- 如果你追求高性能、动态配置、全开源,选 APISIX。
- 如果你在Service Mesh 或需要深度定制,选 Envoy。
建议在选型前,用本文的 Docker Compose 示例在本地跑一遍,结合自身业务压测。
下一步:可以进一步研究各网关的 Kubernetes Ingress Controller 实现,以及如何与 CI/CD 集成。
—
本文代码已上传至 GitHub,可访问 示例仓库 获取完整配置。