☰
从Kong到APISIX:API网关的架构进化与AI网关新战场
2026/9/30 20:03:28 网站建设 项目流程

如果你在2025年还在把 API 网关当做一个只会做路由转发和限流的组件,那你很可能已经被技术演进甩开了一个身位。我从 2019 年开始在生产环境折腾 API 网关,从 Kong 一路用到 Apache APISIX,中间经历了技术选型、大规模迁移、架构重构,眼看着 APISIX 从一个挑战者变成了 CNCF 顶级项目,又看着它把触角伸向 AI 网关这个全新的战场。这篇文章不聊虚的,就聊聊 APISIX 这些年到底做对了什么,以及它凭什么从 Kong 手里抢走用户,又靠什么在 AI 网关这个新赛道上站稳脚跟。

先说结论:APISIX 的崛起不是靠营销,而是靠几个非常硬核的工程决策——用 etcd 做配置中心、用 radix tree 做路由匹配、用插件链机制把所有扩展能力做成了标准件。而它转向 AI 网关,也不是为了蹭热点,而是传统网关在面对大模型流式响应、Token 计量、多模型路由这些新需求时,是真的扛不住了。下面我把这些拆开讲。

1. 从"挑战者"到"主流选择":APISIX 的设计底气在哪

1.1 为什么 Kong 的"插件心智"被挑战

Kong 在 2015 年到 2019 年这几年间,几乎是 API 网关的代名词。它的核心卖点是基于 Nginx 和 OpenResty,把认证、限流、日志这些通用能力做成了插件,用户通过配置就能组合出想要的网关行为。这个思路在当时非常先进,因为传统的 Nginx 配置方式是在 conf 文件里写死各种 location 和 rewrite 规则,改一次配置就要 reload 一次,运维成本很高。Kong 用数据库存储配置,用 Admin API 动态下发,解决了配置热更新的问题。

但用久了你就会发现几个别扭的地方。第一,Kong 的配置存储在 PostgreSQL 或 Cassandra 里,数据面和控制面之间的同步延迟在极端情况下会放大,尤其是在多节点部署的时候,配置一致性很难做到实时。第二,Kong 的路由匹配是基于正则表达式遍历的,路由数量上了几千条之后,匹配效率会明显下降。第三,Kong 的插件架构虽然灵活,但插件的执行链是固定写死的,开发者想在某些特殊阶段插入自定义逻辑,往往只能 hack。

我在 2019 年维护过一套 Kong 集群,路由数量到了 3000 多条时,p99 延迟从 5ms 飙到了 15ms 以上。排查下来发现,很大一部分时间花在了路由匹配的正则回溯上。当时我就意识到,这种架构的天花板是肉眼可见的。

1.2 APISIX 的核心重构思路:etcd + 扁平路由 + 插件链

APISIX 在 2019 年开源,2020 年进入 CNCF 孵化,它的设计思路几乎是对着 Kong 的痛点逐一下刀。

首先是配置中心。APISIX 没有选择用关系型数据库,而是选了 etcd。这个选择的底层逻辑是:etcd 天生就是为分布式一致性设计的,watch 机制能让数据面实时感知配置变更,配置下发延迟从秒级降到了毫秒级。而且 etcd 的存储模型是扁平的 KV,天然适合网关这种"路由规则多、配置结构简单"的场景。

其次是路由匹配。APISIX 用 radix tree(基数树)代替了正则遍历。这个数据结构能把公共前缀合并,路由匹配的时间复杂度从 O(N) 降到 O(log N),甚至在很多场景下接近 O(1)。我实测过,在 5000 条路由的规模下,APISIX 的匹配时间稳定在 1ms 以内,这个差距在高并发下会被指数级放大。

第三是插件机制。APISIX 把请求生命周期拆成了 11 个阶段,包括 rewrite、access、before_proxy、header_filter、body_filter、log 等。每个插件只要声明自己挂载在哪个阶段,就能被 APISIX 自动编排执行。这个设计让插件的开发门槛大大降低,也避免了 Kong 那种插件执行链写死的僵硬感。

1.3 颠覆的底层逻辑:控制面与数据面分离的彻底性

APISIX 还有一个被很多人忽略的设计——它把控制面和数据面拆得特别彻底。APISIX 的 Admin API 只负责读写 etcd,真正的数据面节点只从 etcd watch 配置。这意味着你可以随时横向扩容数据面,不需要迁移任何数据库,也没有配置同步延迟的问题。相比之下,Kong 的控制面和数据面虽然在逻辑上分离了,但数据面依然依赖数据库连接来拉取配置,跨地域部署时的延迟问题始终存在。

这个架构上的差异,在云原生环境里被进一步放大。APISIX 可以很自然地融入 Kubernetes,通过 Ingress Controller 实现配置的声明式管理,而 Kong 在做 K8s Ingress 的时候,配置链路明显更重。我在实际迁移中感受很深:同样一套业务,Kong 集群需要 3 个节点做 HA,APISIX 因为配置同步够快,2 个节点就能跑得比原来更稳。

2. 关键能力拆解:APISIX 凭什么能扛住生产流量

2.1 路由匹配:从遍历正则到 radix tree 的进化

路由是网关的灵魂,也是 APISIX 最早打出差异化的一张牌。Kong 当时的路由匹配是逐个遍历路由规则,每条规则里可能包含多个正则表达式,匹配失败就跳到下一条。这种做法的优点是灵活,缺点是慢——尤其是正则回溯导致的性能黑洞。

APISIX 的 radix tree 方案,本质上是用空间换时间。它把每条路由的路径切分成片段,按树形结构存储,匹配时一次遍历就能定位到目标节点。而且 APISIX 在这个基础上还增加了优先级机制(priority 字段),匹配到多个路由时按优先级排序,而不是按添加顺序。这一点在生产环境特别有用——你完全可以让/v1/开头的路由优先匹配到灰度服务,而不会被/healthz这类通用路由截胡。

这里有一个细节值得多说一句:APISIX 的 radixtree 匹配支持 host、method、uri、vars 多维组合。也就是说,你可以定义一条路由只匹配POST /api/v1/users且Host = example.com且 header 里有X-Version: v2的请求。这种组合匹配能力在实际业务里几乎是必备的,因为网关面对的流量从来不是单一的路径匹配。

2.2 插件系统:一个请求生命周期里被拆开的 11 个阶段

APISIX 的插件系统是我见过最接近"乐高积木"的设计。它没有沿用 Nginx 的整套阶段模型,而是把请求处理过程拆成了 11 个阶段:

  • rewrite:重写 URI、修改请求头,适合做 URL 规范化
  • access:核心的认证、限流、路由逻辑都挂在这里
  • before_proxy:在真正转发到上游之前做最后的调整,比如改写 Host 头
  • header_filter、body_filter:响应阶段的修改
  • log:请求结束后的日志记录、指标上报

每个插件执行的先后顺序,由插件的priority字段决定。比如key-auth(认证)的 priority 是 1000,limit-count(限流)的 priority 是 1002,所以限流会在认证之后执行。这个顺序是经过深思熟虑的,因为限流需要先确认请求方身份,才能按用户维度做精准限流。

我踩过一个坑:自定义插件的 priority 设置不当,导致在认证之前就执行了限流逻辑,所有匿名请求都被限制在了同一个计数器里,结果某用户认证失败重试了几次,就把整个 IP 段都限死了。后来才明白,插件的优先级不只是"先执行后执行"的问题,还直接关系到业务逻辑的隔离。

2.3 热更新与健康检查:绕开 reload 的工程智慧

传统 Nginx 改配置要 reload,reload 会断开所有长连接,这在 WebSocket 或 SSE 场景下是致命的。APISIX 的做法是:所有配置变更通过 etcd watch 触发,数据面进程内部动态更新路由和插件配置,不需要 reload。

这背后的实现原理是 APISIX 把路由、服务、上游、消费者这几类对象在内存中做了镜像,当 etcd 推送变更时,数据面会构造一份新的镜像,然后原子切换。这个过程对正在处理的请求是完全透明的,不会有任何连接中断。

健康检查这块,APISIX 支持主动和被动两种模式。主动健康检查是定时探测上游节点,被动健康检查是分析真实请求的响应状态码。生产环境里我的建议是两种都开启,主动检查用于兜底,被动检查用于快速发现异常。配置的关键参数是healthy.interval和unhealthy.failures,前者控制探测频率,后者控制连续失败多少次判定节点不健康。实测下来,被动健康检查发现故障的速度比主动探测快 3 到 5 倍,因为它是直接基于真实流量判断的,不需要等下一个探测周期。

2.4 性能数据的背后逻辑

很多人在比较 APISIX 和 Kong 时会引用各种 benchmark 数据,但我建议你看数据之前先理解两个前提。第一,APISIX 和 Kong 的底层都是 Nginx,所以基础 I/O 能力是同一水平的,真正的差距来自业务逻辑的处理效率。第二,APISIX 的测试结果之所以好看,核心原因是它把路由匹配和配置读取这两个高频操作做到了极致。

我的实测经验是:在同等硬件条件下,APISIX 的 QPS 吞吐比 Kong 高 20% 到 40%,延迟 p99 低 30% 到 50%。这个差距在路由数量超过 1000 条之后会更加明显。如果你的服务只有几十条路由,两者差距可能感知不大,但一旦业务规模上来,这个差距就是实打实的成本差异。

3. AI 网关:传统网关在 LLM 场景下的三个"失灵"时刻

3.1 第一个失灵:流式响应无法限流

传统网关的限流是基于请求数或连接数的。你限制某个用户每秒最多请求 10 次,用的是limit-conn(连接数)或limit-req(请求速率)。但大模型的回答是流式输出的,一个请求可能持续 30 秒甚至几分钟,客户端和服务器之间是一条长时间不关闭的 SSE 连接。

这时候问题来了:如果限制连接数,一个用户两条流式请求就把配额占满了,其他用户全部被拒;如果按请求速率限制,用户只要不频繁发请求,根本限制不住 token 消耗量。真正的计费单位是 token,不是请求数,而传统网关根本没有 token 的概念。

我遇到过的最典型的场景是:一个内部工具接入了 LLM 接口,某个开发者写了个 for 循环批量调用,每秒只发 2 个请求,按传统限流规则完全合法,但 token 消耗量却在几分钟内达到了几十万。如果没有网关层面的 token 计量,这笔账单只能默默吃下。

3.2 第二个失灵:Token 计量颗粒度太粗

传统网关做流量计量,通常按请求数或字节数。请求数不反映真实成本,字节数也无法区分普通文本和大模型生成的 token 结构。甚至到了模型层面,不同模型的 token 单价差异巨大——GPT-4 的 token 价格可能是某些小模型的几十倍。

AI 网关需要的是按 token 维度计量,而且要能让用户自助查询每个 API Key 的消耗。这件事在传统网关上做非常别扭:你得自己解析请求体和响应体,从 JSON 里提取 prompt 和 completion 的内容,再切 token 估算使用量。且不说 GPT 的 tokenizer 和普通文本切分逻辑完全不同,光是解析流式响应(SSE 格式的data:分块)就能把人折腾疯。

3.3 第三个失灵:多模型路由与 fallback 逻辑缺失

传统网关的上游是一个具体的 service——一个 IP 加端口,或者一个域名解析到的集群。但在 AI 场景下,上游往往是多个模型供应商的 API,比如 OpenAI、Claude、本地部署的 Llama。你需要根据请求的模型名、API Key 的权限级别、当前各供应商的可用性,动态选择把请求转发给谁。

更复杂的是 fallback 逻辑。OpenAI 的某个模型不可用了,网关应该自动把流量切到备用模型或备用供应商。这个逻辑如果放在业务代码里,每个接入方都要重复实现一遍,非常容易遗漏和出错。正确的做法是在网关层统一处理,业务方只需要声明"我要用 GPT-4,如果没有就降级到 GPT-3.5",剩下的路由和重试由网关完成。

这三个"失灵"场景合在一起,催生了 AI 网关这个新品类。而 APISIX 作为现有网关里响应最快的项目之一,直接把这些能力做成了标准插件。

4. APISIX 的 AI 网关方案落地实操

4.1 快速搭建一个带 AI 能力的 APISIX 实例

我用 Docker 方式演示,这是最快能跑起来的路径。先创建一个 docker-compose.yml 文件:

version: "3.8" services: etcd: image: bitnami/etcd:3.5 environment: - ALLOW_NONE_AUTHENTICATION=yes - ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379 ports: - "2379:2379" - "2380:2380" apisix: image: apache/apisix:3.9.0 depends_on: - etcd ports: - "9080:9080" - "9180:9180" volumes: - ./apisix_config/config.yaml:/usr/local/apisix/conf/config.yaml:ro

启动之后,默认的 Admin API 在 9180 端口,需要配置一个 admin_key。我们通过 Admin API 创建一个上游,指向一个兼容 OpenAI 协议的 LLM 服务:

curl -i http://127.0.0.1:9180/apisix/admin/upstreams/1 \ -H "X-API-KEY: your_admin_key" \ -X PUT \ -d '{ "type": "roundrobin", "nodes": { "your-llm-endpoint:443": 1 }, "scheme": "https", "pass_host": "node" }'

这里的pass_host: node很关键。默认情况下 APISIX 会用上游节点的地址作为 Host 头转发,但很多 LLM API 需要 Host 保持为原始域名,否则会报 401 或 403。如果你的 LLM 服务也是类似要求,记得把pass_host改成node。

4.2 配置 token 限流的关键参数

APISIX 3.9 之后提供了limit-token插件,专门处理 token 维度的限流。它的工作原理是解析请求体中的prompt字段和响应体中的completion字段,估算 token 消耗,然后按时间窗口累加计数。

{ "plugins": { "limit-token": { "window_size": 60, "window_type": "sliding", "token_limit": 100000, "rejected_code": 429, "header_limit": "X-Token-Limit" } }, "upstream_id": "1", "uri": "/v1/chat/completions" }

配置里window_type我建议选sliding(滑动窗口),而不是fixed(固定窗口)。原因是 LLM 的请求长度变化极大,一个 5 秒的长请求可能消耗几万 token,如果在固定窗口的最后 10 秒进入,会把下一个窗口的配额挤占掉。滑动窗口按秒级切分,抗突发能力更强。

token_limit的设定要看你的业务模型。如果是内部员工使用,建议按账号维度分配;如果是对外开放 API,建议按 API Key 维度分配。APISIX 的limit-token插件支持consumer_name字段,你可以和key-auth插件配合,实现按用户限流:

{ "plugins": { "key-auth": {}, "limit-token": { "token_limit": 50000, "consumer_name": "user-001" } } }

4.3 多模型供应商路由配置

APISIX 做多供应商路由有三种方式,我按推荐程度排序:

第一种,基于 uri 前缀区分。比如/openai/开头的请求走 OpenAI,/claude/开头的走 Anthropic。这种最简单,两个 route 配置就行,互不干扰。

第二种,基于请求体里的 model 字段动态路由。这需要用到 APISIX 的vars匹配能力,或者配合serverless-pre-function插件做自定义逻辑。

第三种,用 APISIX 的ai-proxy插件做统一入口。这个插件是 APISIX 3.9 引入的 AI 网关核心插件,它能把多个上游包装成统一的 OpenAI 兼容接口,业务方只需对接你公开的 gateway 地址,不需要关心背后是哪个模型供应商。

我实际用的最多的是第一种和第三种结合。第三种的好处是封装度高,但前提是业务方的模型名和你的上游模型名能对应上。如果你内部有模型命名规范,强烈建议统一用ai-proxy。

配置示例:

{ "plugins": { "ai-proxy": { "provider": "openai", "auth": { "header": "Authorization", "secret": "your_api_key" }, "model": { "provider": "openai", "name": "gpt-4o", "options": { "temperature": 0.7 } } } }, "uri": "/v1/chat/completions" }

4.4 从 Kong 迁移到 APISIX 的踩坑记录

迁移过程最大的坑不是功能缺失,而是配置模型的思维转换。Kong 的配置是 Service、Route、Upstream、Consumer 四件套,APISIX 也有类似的模型,但行为和命名有很多差异。

第一个坑是路由匹配顺序。Kong 按接口添加顺序匹配,APISIX 按 priority 和匹配精度。迁移时如果不注意,很容易出现"原本能命中的路由突然 404"的情况。建议迁移后先跑一遍全量路由的 smoke test,用真实请求验证每条业务链路。

第二个坑是插件的配置格式。以限流插件为例,Kong 的rate-limiting用minute/hour/day这种时间单位,APISIX 的limit-req用rate和burst两个参数。口径完全不一样。我的经验是先梳理业务上真实的限流诉求(每秒多少请求、允许多少突发),再反推插件参数,而不是按原来的数值原样照搬。

第三个坑是日志格式。Kong 的 access log 默认格式和 APISIX 有差异,如果你有日志采集系统(比如 ELK 或 Loki),字段映射需要重新做。尤其是真实客户端 IP、上游响应时间、请求体大小这些字段,两边字段名不一样,迁移后第一天的日志告警可能全是解析错误。

5. 生产级排查与避坑经验

5.1 路由冲突的经典排查

APISIX 的路由有精确匹配和前缀匹配两种模式,uri: /api/*是前缀匹配,uri: /api/v1/users是精确匹配。当两条路由同时命中一个请求时,APISIX 会优先选择"匹配精度更高"的那条。听起来很合理,但如果你使用了通配符或正则,这个"精度更高"的判定就会变得不那么直观。

一次线上事故让我记忆犹新:灰度环境的流量突然全部打到了生产集群,原因是灰度路由的 uri 定义成了/api/*,生产路由的 uri 是/api/v1/order,生产路由的 priority 默认是 0,灰度路由的 priority 也没设置。结果新版本 APISIX 把精度更高的/api/v1/order优先匹配了,灰度流量直接透传到了生产。所以我的建议是:所有带环境隔离需求的路由,必须显式设置 priority,不能依赖默认匹配顺序。

5.2 插件顺序导致的诡异限流失效

插件的执行顺序是按 priority 排序的,但 APISIX 文档里写的是"建议在配置时声明插件依赖",实际执行却不检查依赖关系。比如limit-conn和limit-req都是限流插件,priority 分别是 1001 和 1000,如果业务方同时配了这两个插件,先执行的是limit-conn(连接数限制)。如果你本想用limit-req限制 QPS,但limit-conn的连接数限制先触发,限流的效果就是:并发连接超过阈值才拒绝请求,QPS 完全没被限制住。

这类问题排查起来特别隐蔽,因为它不负责任何报错,只是让你看到"限流配置了但没生效"。建议限流相关插件一律在 rewrite 阶段用serverless-pre-function显式挂载,避免和其他插件混在一起。

5.3 etcd 抖动对网关的影响

APISIX 对 etcd 的依赖是强依赖,如果 etcd 集群抖动,网关的配置更新会失败,甚至在极端情况下会导致数据面读取配置超时。我自己遇到过 etcd 磁盘 IO 飙高,导致 watch 事件堆积,APISIX 处理配置变更的延迟从毫秒级涨到了 3 秒多。

预防措施有两层。第一层是 etcd 侧:给 etcd 独立部署,不要和业务数据库混在一起,并配置好磁盘告警。第二层是 APISIX 侧:开启配置缓存,并设置config_cache_enabled: true,这样即使 etcd 短暂不可用,数据面也能用缓存配置继续服务,避免整个网关雪崩。

5.4 几个容易被忽略的配置项

说三个我后来才补上的关键配置。

第一个是plugin_attr里的server_header。默认 APISIX 会返回Server: APISIX/3.9.0头,安全评估的时候这个版本号信息很容易被利用。建议改成Server: nginx或者自定义字符串。

第二个是router配置里的http_accept行为。APISIX 默认支持application/json,但如果客户端没有带Accept头,某些路由可能会返回 406。如果你有老客户端没兼容这个行为,可以在config.yaml里关掉强制 Accept 检查。

第三个是enable_resolv_search_opt。如果你在上游节点里配置了域名,而且该域名在多个 search domain 下都能解析,这个参数控制 APISIX 是否启用 Nginx 的 search domain 机制。默认是注释状态,如果你的容器环境有多个 search domain,建议显式开启测试,否则上游解析可能飘到意想不到的 IP。

最后再分享一个经验。不要在生产环境一上来就跑最新版本,APISIX 的 alpha、beta、stable 版本差异很大,社区推荐的是 2.x 的最后几个 patch 版本和 3.x 的稳定版。我经历过 3.8 到 3.9 的一次升级,ai-proxy插件的配置格式有 Breaking Change,升级前如果不读 Release Notes,线上直接报 400。以后每次升级前,我都会像看前女友朋友圈一样仔细读一遍变更条目,该备份备份,该预发预发,这样才能保证网关这个"总闸门"永远稳稳当当的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询