API 网关选型实战:Kong、APISIX、Envoy 深度对比与落地指南

By | 2026年9月16日

为什么 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)。

六、选型决策树

根据团队情况选择:

  1. 团队规模小,需要快速上线 → Kong(文档丰富,社区大,DB-less 简单)
  2. 云原生环境,追求高性能和动态 → APISIX(etcd 热更新,性能好,全开源)
  3. 已有 Service Mesh 或需要深度定制 → Envoy(配合 Istio 或自研控制平面)
  4. 需要多语言插件 → APISIX(支持 Java、Go、Python 等)
  5. 需要企业级支持 → 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,可访问 示例仓库 获取完整配置。