Apache APISIX 从入门到原理:架构、路由、插件与生产实践
Apache APISIX 是建立在 NGINX、OpenResty 与 LuaJIT 之上的动态 API Gateway。它并不只是把请求从入口转发到后端,而是把路由、认证、限流、负载均衡、服务发现、灰度发布、缓存、可观测性等横切能力集中到流量入口统一治理。
本文从可运行的安装与 Admin API 实践出发,进一步拆解 APISIX 的数据面、控制面、etcd 动态配置、RadixTree 路由、Upstream 负载均衡、插件生命周期、服务发现、Standalone 与 Kubernetes 部署等内部机制,并补充生产环境安全、性能、版本差异与故障排查方法。
APISIX 到底解决什么问题
在单体应用中,一个 Nginx 配置可能就足够:
1 | |
但进入微服务以后,一个请求可能面对几十甚至几百个服务:
1 | |
每个服务又可能存在多个实例:
1 | |
同时还会出现大量与业务无关、却必须统一解决的问题:
- API 应该转发到哪个服务;
- 一个服务的多个实例如何负载均衡;
- 服务实例扩缩容后如何动态发现;
- API 是否需要登录;
- 哪些 Consumer 可以访问;
- 一个 IP 每秒允许访问多少次;
- 下游异常时是否熔断;
- 新版本如何只放 5% 流量;
- 是否需要修改请求头;
- 是否需要缓存上游响应;
- 如何记录日志、Metrics 和 Trace;
- HTTPS 证书如何统一管理;
- 配置变化后能不能立即生效。
如果把这些逻辑全部写进业务服务,就会形成:
1 | |
而真正属于订单服务的,其实只有最后一项。
API Gateway 的核心价值,就是把这些与流量有关、但与业务领域逻辑无关的能力从业务服务中抽离出来。
Apache APISIX 是 Apache 顶级项目,官方将其定位为动态、实时、高性能的 API Gateway。当前官方稳定文档版本为 APISIX 3.17.0,发布时间为 2026 年 6 月 15 日。
从系统架构角度,可以把 APISIX 看成:
1 | |
所以它并不是单纯的“Nginx 管理页面”。
建立 APISIX 的整体心智模型
先不要急着记 Route、Service、Upstream 等对象,先看完整系统。
flowchart LR
Client[Client / App / Browser]
subgraph Gateway["APISIX Data Plane"]
Nginx[NGINX / OpenResty]
Router[Route Matcher<br/>libradixtree]
Plugins[Plugin Engine]
Balancer[Load Balancer]
end
Admin[Admin API]
UI[Dashboard]
Controller[Ingress Controller / ADC]
ETCD[(etcd)]
Registry[Service Registry<br/>Nacos / Consul / Kubernetes / Eureka]
U1[Upstream A]
U2[Upstream B]
U3[Upstream C]
OBS[Prometheus / Logs / Tracing]
Client --> Nginx
Nginx --> Router
Router --> Plugins
Plugins --> Balancer
Balancer --> U1
Balancer --> U2
Balancer --> U3
Admin --> ETCD
UI --> Admin
Controller --> Admin
ETCD -->|watch config changes| Gateway
Registry -->|service discovery| Gateway
Gateway --> OBS
这里有几个非常重要的边界。
数据面 Data Plane
真正处理用户请求的是 APISIX Data Plane:
1 | |
用户的每个 HTTP 请求都会经过这里。
它负责:
- 接收连接;
- TLS;
- Route 匹配;
- Plugin 执行;
- Upstream 选择;
- 负载均衡;
- 请求转发;
- 响应处理。
APISIX 的数据面建立在 NGINX、ngx_lua/OpenResty 和 LuaJIT 之上。NGINX 负责成熟、高性能的网络代理能力,Lua 层则承担动态路由、插件、配置等控制逻辑。
控制面 Control Plane
控制面的任务不是代理业务请求,而是管理配置:
1 | |
例如:
1 | |
本质上是在告诉 APISIX:
从现在开始,请按照这条规则处理后续请求。
etcd
在默认的 Traditional / Decoupled 等模式下,etcd 是 APISIX 的配置存储与同步中心。
里面保存的是:
1 | |
APISIX Worker 通过 etcd Watch 感知这些配置变化,然后更新自身内存中的配置。etcd 因而不需要出现在每个用户请求的数据路径上。
Service Registry
服务注册中心和 etcd 不要混为一谈。
例如:
1 | |
可能负责保存:
1 | |
而:
1 | |
负责告诉 APISIX:
1 | |
也就是:
1 | |
即使某些组件理论上可以同时承担两种职责,在 APISIX 架构里也应该先把这两个概念分开理解。
为什么 APISIX 选择 NGINX + OpenResty + Lua
理解 APISIX 最关键的问题不是:
Route 怎么配置?
而是:
为什么已经有 Nginx 了,还需要 APISIX?
答案藏在“动态”两个字里。
原生 Nginx 的典型工作方式
传统 Nginx 配置类似:
1 | |
修改以后通常需要:
1 | |
这对于几十条静态规则完全没有问题。
但如果有:
1 | |
事情就不同了。
如果每次修改 Route 都生成一次新的:
1 | |
然后 Reload:
1 | |
API Gateway 的动态配置能力就会受到 Nginx 静态配置模型限制。
APISIX 的做法
APISIX 不把每条 API Route 都直接写成一个 Nginx location。
更接近:
1 | |
Nginx 负责:
1 | |
Lua/OpenResty 负责:
1 | |
于是:
1 | |
不再意味着:
1 | |
而是:
1 | |
官方对这一设计的解释也是:APISIX 使用 NGINX 作为网络代理基础设施,而把动态路由等能力放入 Lua 层;路由匹配关键路径又使用 C 实现的 Radix Tree,以兼顾动态性和性能。
可以把这种设计理解成:
1 | |
这实际上是 APISIX 很重要的架构取舍:
不是抛弃 Nginx 的性能,而是在 Nginx 之上增加一个动态控制层。
APISIX 动态配置到底是怎么生效的
假设管理员执行:
1 | |
完整过程可以抽象成:
sequenceDiagram
participant O as Operator
participant A as Admin API
participant E as etcd
participant W as APISIX Worker
participant C as Client
O->>A: PUT Route
A->>A: Authentication
A->>A: JSON Schema Validation
A->>E: Persist Configuration
E-->>W: Watch Event
W->>W: Refresh In-Memory Configuration
C->>W: New Request
W->>W: Match New Route
W-->>C: Response
Admin API 会对资源配置进行校验,然后写入配置存储;Worker 监听配置变化并更新运行时配置。这个机制使 Route、Plugin、Upstream 等大量资源的变化不必依赖传统的 Nginx Reload。
因此:
1 | |
而不是:
1 | |
这也是为什么 APISIX 能比较自然地实现:
1 | |
APISIX 中有两类完全不同的配置
这是初学者最容易混淆的地方。
静态运行配置
例如:
1 | |
里面主要配置:
1 | |
它描述的是:
APISIX 这个程序本身应该怎么运行。
例如:
1 | |
生产环境不要直接照抄示例 Secret,应通过 Secret Manager、环境变量或部署平台安全注入。
动态业务配置
包括:
1 | |
它们描述:
请求应该怎么处理。
一般通过:
1 | |
进行管理。
不要直接修改生成后的 nginx.conf
APISIX 会根据自己的配置模板生成 Nginx 配置。
因此:
1 | |
往往是错误做法。
APISIX 再次启动或重新生成配置时,很可能覆盖这些修改。当前官方安装文档明确区分了用户配置 config.yaml 与生成的 nginx.conf,推荐修改 APISIX 配置而不是直接修改生成文件。
快速运行 APISIX
官方 Quick Start
开发环境最快的方式是:
1 | |
然后验证:
1 | |
Quick Start 会启动 APISIX 和 etcd。
需要特别注意:当前官方 Quick Start 为降低学习门槛,会关闭 Admin API 授权,这种配置只适合本地体验,不应该直接复制到生产环境。
Docker Compose
更接近完整实验环境的方式是使用官方 Docker 仓库:
1 | |
部分 Docker 环境仍可能使用:
1 | |
可以查看:
1 | |
确认:
1 | |
等组件是否正常。官方当前安装文档仍提供 Docker Compose 与 Helm 两类常用安装方式,并由容器化安装自动处理 etcd 等依赖。
常用端口
常见默认端口可以先记住两个:
| 端口 | 用途 |
|---|---|
9080 |
APISIX HTTP Gateway |
9180 |
Admin API |
生产环境中端口本身可以修改,因此不要把这些数字硬编码进业务系统。
Dashboard 的当前使用方式
旧版本 APISIX 教程中经常可以看到:
1 | |
这是早期独立 apisix-dashboard 组件的典型部署方式。一些 2022~2023 年文章和 Docker Compose 示例仍然采用这一架构。
当前 APISIX 3.17 文档已经采用内置 Admin UI,默认入口为:
1 | |
并由:
1 | |
控制。Dashboard 最终仍然通过 Admin API 管理 APISIX 资源。
所以遇到教程要求访问:
1 | |
不要立刻怀疑安装坏了,先看它写的是哪个 APISIX / Dashboard 版本。
Admin API:理解 APISIX 的第一把钥匙
APISIX 大量动态资源都可以通过 REST API 管理。
基础路径:
1 | |
例如:
1 | |
Admin API 支持常见 CRUD 操作:
| Method | 含义 |
|---|---|
GET |
查询 |
PUT |
创建指定 ID 或完整更新 |
POST |
创建并由系统分配 ID |
PATCH |
局部修改 |
DELETE |
删除 |
Upstream 等资源当前同时支持完整 PATCH 和字段路径 PATCH。
获取 Admin Key
普通安装环境可以从配置中读取:
1 | |
后续统一:
1 | |
本文后面的 Admin API 示例均按启用了 Admin API 鉴权的正常环境书写。
跑通第一条 Route
创建 Route:
1 | |
请求:
1 | |
完整数据流:
1 | |
这也是 APISIX 最小工作模型:
1 | |
Route 负责回答:
1 | |
Upstream 负责回答:
1 | |
APISIX 核心资源模型
理解 APISIX 后续所有配置前,应该先把几个核心对象彻底区分清楚。
| 资源 | 核心职责 |
|---|---|
| Route | 判断请求匹配哪条规则 |
| Upstream | 描述后端节点与负载均衡 |
| Service | 复用一组 Route 的公共能力 |
| Plugin | 给请求增加认证、限流、改写等能力 |
| Plugin Config | 复用一组插件配置 |
| Consumer | API 调用方身份 |
| Credential | Consumer 的认证凭证 |
| Consumer Group | 一组 Consumer 的公共插件策略 |
| Global Rule | 全局执行的 Plugin |
| SSL | TLS 证书资源 |
| Secret | 安全引用密码、Token、证书等敏感值 |
它们之间大致是:
flowchart TD
Client[Client]
Route[Route]
Service[Service]
PluginConfig[Plugin Config]
Upstream[Upstream]
Consumer[Consumer]
Credential[Credential]
ConsumerGroup[Consumer Group]
GlobalRule[Global Rule]
Plugins[Plugins]
Backend[Backend Nodes]
Client --> Route
Route --> Service
Route --> PluginConfig
Route --> Upstream
Service --> Upstream
Credential --> Consumer
Consumer --> ConsumerGroup
Consumer --> Plugins
Route --> Plugins
Service --> Plugins
PluginConfig --> Plugins
GlobalRule --> Plugins
Upstream --> Backend
下面逐个拆开。
Route:APISIX 如何判断一个请求应该去哪里
Route 是整个 APISIX 最重要的资源之一。
一条 Route 可以包含:
1 | |
例如:
1 | |
它表示:
1 | |
Route 不是只有 URI
实际系统很可能需要:
1 | |
例如:
1 | |
那么:
1 | |
可以匹配到新版本。
而普通请求:
1 | |
进入默认版本。
这给 APISIX 带来了非常灵活的:
1 | |
能力。
APISIX 为什么使用 RadixTree 做路由
假设存在:
1 | |
最简单的实现当然可以:
1 | |
但当 Route 数量不断增大时,每个请求都线性遍历所有规则并不理想。
APISIX 使用 libradixtree,基于 Adaptive Radix Tree 实现高效 URI 路由匹配。当前文档中的典型匹配方式包括 Exact Match 与 Prefix Match,并按照 URI 匹配深度等规则选择候选 Route。
例如:
1 | |
可以做精确匹配。
而:
1 | |
可以表示前缀匹配。
可以把 Radix Tree 粗略理解成:
1 | |
查找:
1 | |
时,可以沿路径向下寻找,而不是简单把请求拿去和所有 Route 逐条比较。
Route Priority
如果存在多条可能匹配的 Route,可以通过:
1 | |
帮助控制优先级。
工程上最好做到:
尽量让路由条件本身清晰互斥,而不是大量依赖 priority 修复重叠规则。
否则半年后会出现:
1 | |
然后所有人一起考古。
Upstream:真正决定请求发给谁
Route 决定:
1 | |
Upstream 决定:
1 | |
例如:
1 | |
结构:
1 | |
APISIX 当前 Upstream 支持负载均衡、健康检查、重试、连接/发送/读取超时、Host 传递、HTTP/HTTPS/gRPC 等协议,以及连接池参数。
独立管理 Upstream
不推荐每条 Route 都复制:
1 | |
例如:
1 | |
可以先建立:
1 | |
1 | |
然后 Route:
1 | |
以后扩容:
1 | |
只需要修改 Upstream。
所有引用它的 Route 都一起生效。
这就是对象化配置的价值:
1 | |
官方同样推荐在多个 Route 重复使用后端配置时独立创建 Upstream,通过 upstream_id 复用。
APISIX 的负载均衡算法
当前 Upstream 常用算法包括:
| 算法 | 用途 |
|---|---|
roundrobin |
加权轮询 |
chash |
一致性 Hash |
ewma |
根据历史延迟选择节点 |
least_conn |
优先选择连接压力较低的节点 |
APISIX 当前 Admin API 文档定义了这些 Upstream 类型,其中 roundrobin 为默认算法,chash 可以按变量、Header、Cookie 或 Consumer 做一致性哈希。
roundrobin
例如:
1 | |
第二个节点拥有更高权重。
适合:
1 | |
例如:
1 | |
chash
一致性 Hash 适合:
1 | |
可以基于:
1 | |
例如:
1 | |
如果客户端:
1 | |
相同 sid 在节点拓扑稳定时会倾向于进入相同 Backend。
least_conn
适合请求耗时差异比较大的系统。
大致思想不是:
1 | |
而是:
1 | |
当前实现依据节点活动连接数量与权重进行选择。
EWMA
EWMA 会把历史响应延迟纳入计算。
如果:
1 | |
即使两个节点理论权重相同,也可以尽量避免持续给慢节点施加更多压力。
Upstream 超时必须明确配置
网关非常容易出现一个反模式:
1 | |
然后:
1 | |
Upstream 可以设置:
1 | |
三者对应:
1 | |
默认值未必适合所有业务。
例如:
1 | |
和:
1 | |
显然不应该使用完全相同的超时策略。
Retry 不是免费的可靠性
APISIX Upstream 支持:
1 | |
但看到 Retry 时不要自动理解成:
1 | |
真正的问题是:
1 | |
例如:
1 | |
后端实际上已经扣款:
1 | |
但返回过程中连接中断。
Gateway 如果错误地重新执行:
1 | |
可能变成第二次扣款。
因此 Retry 必须和:
1 | |
一起设计。
正确的思路不是:
请求失败就多重试几次。
而是:
只有明确知道能够安全重试的失败才应该重试。
Upstream 健康检查
APISIX 支持主动和被动健康检查。
Active Health Check
Gateway 主动发:
1 | |
判断:
1 | |
例如官方形式:
1 | |
APISIX 的 Upstream 可以配置主动/被动检查,并结合 Retry 在后端故障时完成节点摘除与恢复判断。
Passive Health Check
被动检查则观察真实业务请求:
1 | |
连续异常后将节点标记为 Unhealthy。
被动检测有一个非常容易忽略的问题:
1 | |
因此生产环境通常会把:
1 | |
组合使用,而不是只依赖被动健康检查。官方健康检查说明也特别指出了这一恢复问题。
Service:把公共配置从 Route 中抽出来
假设订单 API:
1 | |
每条 Route 都可能使用同一个:
1 | |
如果每条都写:
1 | |
会产生大量重复。
Service 就是为了:
1 | |
官方将 Service 定义为一组 API/Route 的抽象,可以承载它们共同的 Upstream 与 Plugin 配置;Route 上相同 Plugin 的配置可以覆盖 Service 层配置。
创建:
1 | |
Route:
1 | |
Plugin Config:专门复用插件组合
如果多个完全不同的 Service 都需要:
1 | |
可以建立 Plugin Config:
1 | |
然后:
1 | |
这样能够进一步减少策略复制。
需要注意:
Service是业务服务抽象,而Plugin Config是插件策略组合抽象。
两者不是同一个概念。
Consumer 与 Credential
Consumer 表示:
1 | |
例如:
1 | |
而 Credential 表示:
1 | |
当前 APISIX 已经把 Credential 作为独立资源,可以让同一个 Consumer 拥有多个认证凭证,而不仅仅把 Key 直接塞进 Consumer 本身。
例如:
1 | |
这样做非常适合密钥轮换:
1 | |
而不需要瞬间让所有客户端一起换 Key。
APISIX 插件体系
如果 Route 和 Upstream 解决的是:
1 | |
Plugin 解决的是:
1 | |
比如:
1 | |
APISIX 当前提供大量内置插件,覆盖认证、安全、流量控制、请求/响应改写、缓存、灰度、可观测性以及其他协议等能力。
典型分类如下:
| 类型 | 示例 |
|---|---|
| Authentication | key-auth、jwt-auth、basic-auth、openid-connect |
| Security | cors、ip-restriction、uri-blocker |
| Traffic | limit-count、limit-req、limit-conn |
| Resilience | api-breaker |
| Rewrite | proxy-rewrite、response-rewrite |
| Cache | proxy-cache |
| Canary | traffic-split |
| Metrics | prometheus |
| Tracing | opentelemetry、zipkin、skywalking |
| Logging | http-logger、kafka-logger、loki-logger |
| Protocol | gRPC、Dubbo、Kafka 等相关插件 |
这也是 APISIX 与“普通反向代理”最大的区别之一:
很多网关能力不是硬编码进 APISIX Core,而是插件化。
一个请求经过哪些 Plugin Phase
APISIX Plugin 并不是随机执行的。
典型生命周期可以理解为:
flowchart LR
A[Client Request]
B[Route Match]
C[rewrite]
D[access]
E[before_proxy]
F[Upstream]
G[header_filter]
H[body_filter]
I[Client Response]
J[log]
A --> B
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
H --> I
I --> J
官方 Plugin 生命周期定义了 rewrite、access、before_proxy、header_filter、body_filter、log 等阶段。
rewrite
适合:
1 | |
例如当前 APISIX 插件开发文档明确规定认证插件通常在 rewrite 阶段工作。
access
适合:
1 | |
这是请求进入 Upstream 之前最常见的插件阶段之一。
before_proxy
在真正代理上游之前执行。
header_filter
用于修改上游响应 Header。
例如:
1 | |
body_filter
对响应 Body 做处理。
log
请求基本处理完成后:
1 | |
等逻辑可以在这里收尾。
插件优先级不是配置文件里的先后顺序
假设:
1 | |
不要认为:
1 | |
APISIX Plugin 有:
1 | |
同一执行阶段中:
1 | |
自定义插件也必须避免与已有 Plugin 使用重复 Priority。官方建议在开发自定义插件时通过 Control API /v1/schema 检查现有插件优先级。
同一个 Plugin 配在多个资源上,谁生效
例如:
1 | |
当前 APISIX 对同一个本地 Plugin 配置的合并优先级可以概括为:
1 | |
Global Rule 属于另一层全局执行语义,不能简单理解成被 Route 覆盖;全局插件会在对象级插件之前执行。
这个设计非常适合做:
1 | |
例如:
1 | |
Global Rule
某些规则不应该一条 Route 一条 Route 地配置。
例如:
1 | |
这时可以使用:
1 | |
思路:
1 | |
例如:
1 | |
这样不需要:
1 | |
实战:基于 IP 的固定窗口限流
APISIX 提供三类常见限流插件:
| Plugin | 控制目标 |
|---|---|
limit-req |
请求速率 |
limit-count |
一个时间窗口中的请求总数 |
limit-conn |
并发连接/请求数量 |
其中当前 limit-count 使用固定窗口计数算法。
例如:
1 | |
含义:
1 | |
所以:
1 | |
超出:
1 | |
多 APISIX 节点下,local 限流不是全局限流
这是生产环境非常常见的坑。
假设:
1 | |
每台:
1 | |
那么理论上整个 Gateway Cluster 可能承受:
1 | |
因为:
1 | |
只存在当前节点内存。
当前 limit-count 支持:
1 | |
三种 Counter Storage Policy。需要集群共享配额时,可以使用 Redis 或 Redis Cluster。
所以设计限流前一定要先问:
1 | |
这比“限多少 QPS”更重要。
实战:key-auth
创建 Consumer:
1 | |
创建 Credential:
1 | |
Route 开启认证:
1 | |
客户端:
1 | |
当前 key-auth 默认从:
1 | |
或 Query String 中读取 Key,Header 优先级更高;hide_credentials=true 可以阻止认证凭证继续被代理到 Upstream。
生产环境通常更推荐:
1 | |
而不是:
1 | |
因为 Query String 更容易出现在:
1 | |
中。
Consumer 能与限流组合
例如:
1 | |
APISIX 可以先:
1 | |
得到:
1 | |
再使用:
1 | |
按:
1 | |
进行限流。
还可以组合:
1 | |
当前 limit-count 支持 var_combination,因此可以按照多个变量组合生成 Counter Key。
这比简单 IP 限流更适合真正的 SaaS API:
1 | |
共同参与限流策略。
实战:proxy-cache
缓存链路:
1 | |
例如:
1 | |
适合:
1 | |
不适合随便缓存:
1 | |
当前 proxy-cache 支持 Memory 与 Disk 两类缓存,并能控制 Cache Key、Method、HTTP Status、TTL、Cache-Control、Vary、Consumer Isolation 等行为。默认情况下还会避免缓存带有 private、no-store、no-cache 等上游 Cache-Control 语义的响应。
缓存真正难的不是:
1 | |
而是:
1 | |
所以生产设计时应该先确定:
1 | |
再启用 Cache。
实战:灰度发布
假设:
1 | |
目标:
1 | |
创建两个 Upstream:
1 | |
然后使用:
1 | |
概念配置:
1 | |
APISIX 当前 traffic-split 可以依据条件和 Weight 将流量分配到不同 Upstream,适合 Canary 与 Blue-Green 等发布模式。
灰度过程可以做成:
1 | |
每一步观察:
1 | |
发现异常:
1 | |
即可快速回滚流量。
需要注意,在很小的请求样本下,权重得到的是统计意义上的比例,而不是保证“连续 10 个请求一定精确 9:1”。官方文档也提醒小样本或状态重置情况下实际比例可能存在偏差。
服务发现:不要把 Backend IP 写死
最简单的 Upstream:
1 | |
但微服务环境中:
1 | |
都会造成:
1 | |
因此更理想的方式是:
1 | |
例如:
1 | |
当前 APISIX 文档列出了 Nacos、Consul、Eureka、Kubernetes、DNS 等多种服务发现方式。
Upstream 可以表达为:
1 | |
不再直接关心:
1 | |
而是:
1 | |
当前 Upstream Admin API 也明确规定:
1 | |
和:
1 | |
属于两种不同的 Backend 获取方式。
etcd 与 Nacos 的职责再区分一次
如果同时存在:
1 | |
一个很典型的职责分工是:
1 | |
etcd 保存:
1 | |
Nacos 保存:
1 | |
这就是:
1 | |
和:
1 | |
两个层次。
自定义 Lua Plugin
当内置 Plugin 不能满足需求时,可以开发自定义 Lua Plugin。
例如,希望所有响应增加:
1 | |
一个简化 Plugin 可以写成:
1 | |
这里体现了 APISIX Plugin 的几个核心组成:
1 | |
生产使用前需要检查 Priority 是否与已安装 Plugin 冲突,上面的 23 只是示例值。官方插件开发文档要求自定义 Plugin 定义 JSON Schema,并通过 core.schema.check 完成配置校验。
自定义 Plugin 的加载路径
可以通过:
1 | |
加载外部 Lua 代码。
目录结构:
1 | |
需要时再把 Plugin 加入:
1 | |
这里有一个杀伤力很强的坑:
一旦显式配置
plugins:,这个列表会替换 APISIX 默认插件列表,而不是在默认列表上自动追加。
因此如果只写:
1 | |
有可能无意中把原本需要的内置插件全部移除。
官方插件开发文档专门对此进行了 Warning。
Java、Go、Python 能不能开发 Plugin
可以。
APISIX 支持 External Plugin Runner。
架构类似:
1 | |
External Plugin Runner 以 Sidecar 方式运行,APISIX 把请求相关信息通过 RPC 交给 Runner,由 Runner 创建相应请求上下文、执行外部插件并把结果返回。
这对 Java 团队很有吸引力,但需要理解它与 Lua Plugin 的架构差别:
1 | |
这意味着 External Plugin 会额外增加:
1 | |
如果逻辑简单且团队能够维护 Lua:
1 | |
通常路径更短。
如果逻辑高度依赖:
1 | |
External Plugin Runner 才更有价值。
APISIX 的三种部署模式
当前 APISIX 正式区分:
1 | |
Traditional
结构:
1 | |
同一个 APISIX 实例同时承担:
1 | |
典型端口:
1 | |
适合:
1 | |
Decoupled
将:
1 | |
和:
1 | |
逻辑分离。
flowchart LR
Admin[Admin / CI / Platform]
CP[APISIX Control Plane]
ETCD[(etcd)]
DP1[APISIX Data Plane 1]
DP2[APISIX Data Plane 2]
DP3[APISIX Data Plane 3]
Client[Clients]
Backend[Backends]
Admin --> CP
CP --> ETCD
ETCD --> DP1
ETCD --> DP2
ETCD --> DP3
Client --> DP1
Client --> DP2
Client --> DP3
DP1 --> Backend
DP2 --> Backend
DP3 --> Backend
这样可以:
1 | |
完全留在内部控制网络。
公网只暴露:
1 | |
从安全和大型生产架构角度,这通常比把 Admin API 与业务 Gateway 放在同一个暴露面上更合理。
Standalone
Standalone 不要求依赖默认的 etcd 配置中心。
数据可以来自:
1 | |
或当前提供的:
1 | |
适合:
1 | |
Standalone 文件模式
可以把配置写成:
1 | |
Standalone File 模式会周期性检查配置文件变化,当前官方文档要求 YAML 配置以:
1 | |
结束,以帮助 APISIX 判断配置文件已经完整写入。
这个设计看起来只是一个小细节,实际上解决了很重要的问题:
1 | |
#END 相当于告诉 Reader:
1 | |
Standalone API-driven Mode
当前 APISIX 还提供 Standalone API-driven Mode。
思想变成:
1 | |
而不是:
1 | |
这种模式特别适合:
1 | |
因为可以把 APISIX 当成:
1 | |
由外部控制系统负责 Desired State。当前官方文档已经把 API-driven Standalone 作为独立的 Standalone 使用方式。
Docker 与生产环境
Docker Compose 很适合:
1 | |
生产环境则至少应该考虑:
1 | |
典型结构:
flowchart LR
Client[Internet]
LB[Cloud LB / LVS / Nginx]
A1[APISIX 1]
A2[APISIX 2]
A3[APISIX 3]
E1[(etcd 1)]
E2[(etcd 2)]
E3[(etcd 3)]
Backend[Microservices]
Client --> LB
LB --> A1
LB --> A2
LB --> A3
A1 --> Backend
A2 --> Backend
A3 --> Backend
A1 --> E1
A2 --> E2
A3 --> E3
E1 --- E2
E2 --- E3
E3 --- E1
注意:
etcd 是控制配置基础设施,不应该为了“省机器”随便当普通临时容器使用,更不应该完全不考虑持久化和备份。
Kubernetes 中部署 APISIX
APISIX 不仅能作为普通 VM/Docker 网关,也可以作为 Kubernetes Gateway。
当前 APISIX Ingress Controller 最新文档版本为 2.1.0,并支持:
1 | |
三类 Kubernetes 配置方式。
Helm 安装
当前官方安装方式:
1 | |
安装 APISIX + Ingress Controller:
1 | |
官方还提供直接安装为 Standalone API-driven 模式的 Helm 配置,可以在 Kubernetes 场景中去除 APISIX 默认 etcd 依赖。
Ingress Controller 并不代理业务流量
这是 Kubernetes 使用 APISIX 时一个非常重要的概念。
很多初学者脑中的路径是:
1 | |
实际上更准确的理解是:
1 | |
业务请求则是:
1 | |
Ingress Controller 更像:
1 | |
而 APISIX Gateway 才是:
1 | |
当前 Gateway API 架构同样是由 Controller 将 Gateway、HTTPRoute 等 Desired State 转换为 APISIX 能执行的配置,实际请求最终由 APISIX Gateway 处理。
Kubernetes 数据流
flowchart LR
Developer[Developer]
K8s[Kubernetes API Server]
IC[APISIX Ingress Controller]
GW[APISIX Gateway]
SVC[Kubernetes Service]
P1[Pod 1]
P2[Pod 2]
Client[Client]
Developer -->|kubectl apply| K8s
K8s -->|Watch| IC
IC -->|Sync Gateway Config| GW
Client --> GW
GW --> SVC
SVC --> P1
SVC --> P2
这里实际上存在两条完全不同的链路:
1 | |
和:
1 | |
排查 Kubernetes APISIX 问题时一定要分开。
Gateway API
现在 Kubernetes Gateway 层越来越推荐使用 Gateway API 模型。
典型资源:
1 | |
例如 GatewayClass:
1 | |
Gateway:
1 | |
业务 Route 再通过:
1 | |
挂到 Gateway。
APISIX Ingress Controller 当前同时支持标准 Gateway API,以及用于 APISIX 高级能力扩展的 CRD。
这样架构会比传统:
1 | |
更加结构化。
可观测性
API Gateway 是整个请求链路最理想的观测点之一。
因为大部分请求都经过:
1 | |
因此 Gateway 可以天然看到:
1 | |
APISIX 提供:
1 | |
等插件。
Prometheus
启用:
1 | |
后,APISIX 可以采集 API 请求、延迟等 Metrics 并导出给 Prometheus。
静态配置示例:
1 | |
需要重点观察:
1 | |
如果:
1 | |
说明:
1 | |
如果:
1 | |
就应该继续调查:
1 | |
而不是习惯性地把锅扔给数据库。
Trace
APISIX 位于请求入口,因此非常适合产生或传播:
1 | |
典型链路:
1 | |
然后接入:
1 | |
对于:
1 | |
排查尤其重要。
日志
日志至少应该包含:
1 | |
而不是只有:
1 | |
否则出了生产问题,排查过程很容易变成:
1 | |
API Gateway 日志尤其要注意敏感字段:
1 | |
不要因为 Gateway 能看见就全部写入日志。
Admin API 必须和业务 Gateway 分开看待
APISIX Gateway:
1 | |
处理:
1 | |
Admin API:
1 | |
处理:
1 | |
如果攻击者拿到 Admin API,就可能:
1 | |
所以生产环境绝对不能把:
1 | |
像普通业务 API 一样直接暴露给互联网。
当前官方 Admin API 提供 Admin Key 与 allow_admin 等保护机制;Quick Start 关闭 Admin API 鉴权只是本地体验上的例外。
推荐结构:
1 | |
Admin API 安全建议
生产环境至少做到:
1 | |
如果采用 Decoupled Mode:
1 | |
安全边界会更加清晰。
如果不使用 Dashboard:
1 | |
可以考虑直接关闭 Admin UI。
Secret 不应该明文散落在 Route 中
例如:
1 | |
不应该大量出现:
1 | |
APISIX 当前 Secret 机制可以从:
1 | |
等来源引用敏感数据。
例如环境变量 Secret Reference 可以表达为类似:
1 | |
这样可以把:
1 | |
和:
1 | |
分离。
APISIX 的性能为什么不仅取决于 NGINX
很多人看到:
1 | |
就认为:
1 | |
这并不完整。
Gateway 热路径实际上是:
1 | |
其中每一步都可能产生额外成本。
Route 数量
RadixTree 可以解决大量 URI 路由的核心匹配问题,但如果每条 Route 又附带非常复杂的:
1 | |
条件,依然会增加处理成本。
Plugin 数量
如果一条请求执行:
1 | |
当然比:
1 | |
成本更高。
特别是自定义 Plugin 中不要随意做:
1 | |
External Plugin
外部 Plugin 还增加:
1 | |
因此更应该关注插件是否真的适合放在 Gateway Hot Path。
Redis 限流
policy=local:
1 | |
通常路径很短。
改成:
1 | |
则每次 Counter 操作可能涉及:
1 | |
得到的是:
1 | |
代价则是额外网络与 Redis 依赖。
这就是典型的工程取舍:
1 | |
Logging
如果每个请求都同步调用一个远程日志系统:
1 | |
很快会被日志基础设施反向绑架。
所以高流量系统需要考虑:
1 | |
etcd 不应该位于请求热路径
APISIX 动态架构一个非常重要的特点是:
1 | |
用于:
1 | |
而不是:
1 | |
Worker 拿到配置以后:
1 | |
主要在运行时内存里完成处理。
所以更接近:
1 | |
这意味着 etcd 短暂异常和:
1 | |
不是完全等价的问题。
但 etcd 故障会影响:
1 | |
因此它依然属于关键基础设施。
API Gateway 不是业务 Service Mesh 的替代品
APISIX 可以承担:
1 | |
也可以处理部分:
1 | |
但它和 Service Mesh 解决问题的角度不同。
典型 Gateway:
1 | |
Service Mesh 更偏:
1 | |
Gateway 强项是:
1 | |
Service Mesh 更擅长:
1 | |
实际大型系统完全可能:
1 | |
同时存在,而不是二选一。
APISIX 与普通 Nginx 怎么选
如果需求只是:
1 | |
Nginx 往往已经足够。
没有必要为了:
1 | |
专门上完整 APISIX。
APISIX 更适合:
1 | |
可以简单理解:
1 | |
APISIX 与 Spring Cloud Gateway 怎么看
对于 Java 团队,经常面对:
1 | |
两者不是简单谁替代谁。
Spring Cloud Gateway 的优势往往是:
1 | |
如果团队希望所有 Gateway 逻辑:
1 | |
它会更加自然。
APISIX 则更强调:
1 | |
因此:
1 | |
和:
1 | |
是两个不同的架构取向。
有些企业甚至会形成:
1 | |
不过这种双网关也会增加:
1 | |
除非职责划分非常明确,否则不要为了“架构看起来高级”硬套两层 Gateway。
当前版本与旧教程需要特别区分的地方
APISIX 发展速度较快,网上很多文章的“概念”仍然有价值,但命令和默认配置未必还能直接复制。
截至 2026 年 8 月,官方 APISIX 稳定版本为 3.17.0,Ingress Controller 当前文档版本为 2.1.0。
几个典型差异如下:
| 旧资料中常见内容 | 当前实践 |
|---|---|
| Dashboard 单独部署 | 当前 APISIX 已提供内置 Admin UI |
Dashboard :9000 |
当前默认 Admin UI 位于 :9180/ui |
admin/admin |
不应继续把历史默认账号当当前生产方式 |
| Admin/Gateway/Gateway+Admin 模式名称 | 当前正式分为 Traditional / Decoupled / Standalone |
| Consumer 直接保存所有认证 Key | 当前可以独立使用 Credential |
| Plugin 优先级只有 Consumer/Route/PluginConfig/Service | 当前还存在 Consumer Group |
| 旧版 Ingress CRD 示例 | 当前 Ingress Controller 同时重点支持 Gateway API、Ingress 与 APISIX CRD |
| 所有 APISIX 都依赖 etcd | Standalone 模式可以不依赖默认 etcd |
| Standalone 只有 YAML 文件 | 当前还提供 API-driven Standalone |
早期资料中将 APISIX 划分为 Admin、Gateway、Gateway+Admin 的概念,对理解控制面/数据面仍然很有帮助;2023 年 Docker 示例中的独立 Dashboard 和 :9000 入口则属于当时版本语境。
因此看到任何 APISIX 教程,第一件事建议先确认:
1 | |
而不是直接:
1 | |
网关配置复制错版本,通常不会因为你复制得很认真就变正确。
常见问题排查
9080 无法访问
先看容器:
1 | |
检查:
1 | |
再看:
1 | |
检查端口:
1 | |
然后再判断:
1 | |
不要一上来就怀疑 Route。
返回 404
典型原因:
1 | |
检查:
1 | |
例如 Route:
1 | |
而你请求:
1 | |
Host 实际是:
1 | |
自然可能无法命中。
应该测试:
1 | |
返回 502
一般沿这条链路查:
1 | |
测试 APISIX 节点本身是否能访问:
1 | |
检查:
1 | |
尤其是 HTTPS Upstream:
1 | |
和:
1 | |
配错后,很容易表现成 Gateway 502。
限流为什么多节点不准确
如果配置:
1 | |
Counter 是每个 APISIX 节点自己的。
集群全局配额需要考虑:
1 | |
而不是继续调整:
1 | |
这个问题本质上不是“限流算法不准”,而是:
1 | |
选错了。
Dashboard 9000 打不开
先看 APISIX 版本。
旧教程:
1 | |
当前 3.17:
1 | |
不要跨版本套默认行为。
配置修改后没有生效
Traditional / Decoupled 环境依次检查:
1 | |
Standalone File 模式额外检查:
1 | |
是否正确完成写入,以及 YAML 是否以:
1 | |
结束。
Admin API 返回 401/403
检查:
1 | |
不要为了排查问题直接把:
1 | |
然后忘记改回来。
“暂时全开放一下试试”是许多安全事故的童年照。
K8s Controller 正常,但业务流量不通
把:
1 | |
和:
1 | |
分别排查。
配置链路:
1 | |
流量链路:
1 | |
Controller 日志没有 Error:
1 | |
业务网络一定通。
生产环境架构建议
一套相对完整的 APISIX 生产环境可以设计成:
flowchart TD
Internet[Internet]
DNS[DNS]
LB[Cloud LB / HAProxy / LVS]
subgraph DP["APISIX Data Plane"]
A1[APISIX 1]
A2[APISIX 2]
A3[APISIX 3]
end
subgraph CP["Control Plane"]
Admin[Admin API]
Platform[Gateway Management Platform]
ETCD[(etcd Cluster)]
end
Registry[Service Registry]
Services[Microservices]
Metrics[Prometheus]
Logs[Log Platform]
Trace[Tracing Platform]
Internet --> DNS
DNS --> LB
LB --> A1
LB --> A2
LB --> A3
Platform --> Admin
Admin --> ETCD
ETCD --> A1
ETCD --> A2
ETCD --> A3
Registry --> A1
Registry --> A2
Registry --> A3
A1 --> Services
A2 --> Services
A3 --> Services
A1 --> Metrics
A2 --> Metrics
A3 --> Metrics
A1 --> Logs
A2 --> Logs
A3 --> Logs
A1 --> Trace
A2 --> Trace
A3 --> Trace
职责非常清晰:
1 | |
生产实践检查清单
上线前至少检查这些方面:
Admin Plane
1 | |
Data Plane
1 | |
etcd
1 | |
Route
1 | |
Upstream
1 | |
Plugin
1 | |
Rate Limit
1 | |
Security
1 | |
Observability
1 | |
Release
1 | |
理解 APISIX 最重要的几条原则
学完各种 API 和 Plugin 后,真正值得长期记住的其实不是某个 JSON 字段,而是下面这些设计思想。
配置面和数据面分离
用户请求:
1 | |
配置管理:
1 | |
生产架构越大,这两个边界越应该清晰。
动态配置不应该依赖不断 Reload
APISIX 的核心价值之一,就是通过:
1 | |
让大部分 Gateway Resource 可以实时变化。
Route、Service、Upstream 要解耦
不要把所有东西都塞进:
1 | |
应该建立:
1 | |
Plugin 应该只承担横切逻辑
Gateway Plugin 很适合:
1 | |
不适合:
1 | |
否则 Gateway 会从:
1 | |
慢慢长成:
1 | |
Gateway 不是解决所有问题的地方
APISIX 可以做:
1 | |
但不意味着业务服务不用做:
1 | |
APISIX 可以做:
1 | |
但不意味着业务不用做:
1 | |
APISIX 可以做:
1 | |
但不意味着业务不用设计:
1 | |
APISIX 可以做:
1 | |
但不意味着下游可以完全不考虑:
1 | |
正确的网关设计应该是:
在最合适的层解决最合适的问题。
总结
Apache APISIX 可以先用一个非常简单的模型理解:
1 | |
再向外展开:
1 | |
Route 解决请求匹配,Service 解决公共 API 抽象,Upstream 解决 Backend 与负载均衡,Consumer/Credential 解决调用者身份,Plugin 解决认证、限流、改写、缓存、灰度和可观测等横切能力,etcd 则让这些动态资源能够在默认部署模式下快速同步到 APISIX Worker。
从原理上看,APISIX 最有代表性的设计并不是“插件很多”,而是:
1 | |
理解这些机制以后,再看:
1 | |
都只是同一套核心模型上的不同组合。
真正进入生产环境时,也不应该停留在“能创建 Route”这一层,而应该继续关注:
1 | |
API Gateway 位于几乎所有服务调用之前,所以它既可能成为整套系统最有价值的治理入口,也可能成为影响范围最大的单点。APISIX 提供的是一套强大的流量治理基础设施,而真正决定它是否稳定的,仍然是对控制面、数据面、插件、配置和业务边界是否有足够清晰的工程设计。