Apache APISIX 源码阅读指南
Categories: APISIX
Apache APISIX 源码阅读指南
前言
Apache APISIX 是一个基于 OpenResty(Nginx + LuaJIT)构建的动态、高性能 API 网关。本文档旨在帮助开发者快速建立对 APISIX 源码结构的整体认知,并按合理的顺序深入阅读关键模块。
前置知识建议:
- 熟悉 Nginx/OpenResty 的请求处理阶段(rewrite → access → content → header_filter → body_filter → log)
- 了解 Lua 的基本语法和模块系统
- 了解 etcd 的基本概念(etcd 是 APISIX 的默认配置中心)
一、项目顶层结构总览
apisix/
├── apisix/ # Lua 核心源码(项目的心脏)
│ ├── core/ # 基础库(日志、JSON、配置、请求/响应、缓存等)
│ ├── admin/ # Admin API 实现(CRUD 操作)
│ ├── plugins/ # HTTP 插件(90+ 插件)
│ ├── http/ # HTTP 子模块(路由匹配器等)
│ ├── stream/ # 四层代理(TCP/UDP)
│ ├── control/ # Control API(内部管理接口)
│ ├── discovery/ # 服务发现(Consul、Nacos、Eureka 等)
│ ├── balancer/ # 负载均衡算法
│ ├── secret/ # 密钥管理后端
│ ├── utils/ # 工具模块
│ ├── cli/ # 命令行工具(启停、配置生成)
│ └── init.lua # 主入口,定义所有 OpenResty 阶段钩子
├── bin/apisix # Shell 启动脚本
├── conf/ # 运行时配置
│ ├── config.yaml # 用户配置
│ ├── config-default.yaml # 默认配置
│ └── ...
├── t/ # Perl 测试套件(Test::Nginx)
│ ├── admin/ # Admin API 测试
│ ├── plugin/ # 各插件测试(250+ 文件)
│ ├── core/ # 核心模块测试
│ ├── lib/ # 测试辅助库
│ └── ...
├── docs/ # 文档(en + zh)
└── Makefile # 构建/部署/测试命令
二、启动流程(建议从这里开始阅读)
这是理解整个系统的切入点,沿着启动链路从头读到尾,可以建立对系统骨架的整体认知。
2.1 Shell 入口 → Lua CLI
bin/apisix ──→ apisix/cli/apisix.lua ──→ apisix/cli/ops.lua
bin/apisix(Shell 脚本,约 50 行):定位 OpenResty 和apisix/cli/apisix.lua,然后执行luajit <apisix.lua> <命令参数>apisix/cli/apisix.lua:设置 Lua 模块搜索路径,然后委托给apisix.cli.ops执行apisix/cli/ops.lua:实现init/start/stop/restart/reload等命令
2.2 nginx.conf 生成
当执行 apisix start 时,ops.lua 的 init() 函数会:
- 读取 YAML 配置 → 用
apisix/cli/schema.lua做 schema 校验 - 通过
apisix/cli/ngx_tpl.lua(nginx 配置模板引擎)生成conf/nginx.conf
2.3 Worker 初始化
生成的 nginx.conf 中指定了 Lua 入口为 apisix/init.lua,该文件定义了完整的请求处理生命周期:
-- init.lua 中定义的关键函数
http_init(args) -- 全局初始化(只执行一次)
http_init_worker() -- 每个 worker 进程的初始化
http_access_phase() -- 请求接入阶段(路由匹配、插件执行的核心)
http_header_filter_phase()
http_body_filter_phase()
http_log_phase() -- 日志/上报阶段
http_init_worker() 中的初始化顺序(值得关注):
- 随机种子、LRU 缓存、DNS 解析器
discovery.init_worker()— 服务发现balancer.init_worker()— 负载均衡器admin.init_worker()— Admin APIplugin.load()— 加载所有插件(按优先级排序)router.http_init_worker()— HTTP 路由表初始化require("apisix.http.service").init_worker()— Service 对象初始化- 监听配置变更(etcd watch),实现热更新
三、核心模块体系(apisix/core/)
apisix/core.lua 是一个外观模块(Facade),将所有核心子模块聚合到一个 core 表中:
| 模块 | 文件 | 职责 |
|---|---|---|
core.log |
core/log.lua |
日志输出(warn/error/info/debug) |
core.json |
core/json.lua |
JSON 编解码,支持延迟编码优化 |
core.table |
core/table.lua |
表工具函数(deepcopy、merge 等) |
core.request |
core/request.lua |
请求头部/Body 读写 |
core.response |
core/response.lua |
响应头部设置、退出、CORS |
core.schema |
core/schema.lua |
JSON Schema 校验器封装 |
core.config |
core/config_etcd.lua / core/config_yaml.lua |
配置提供者(etcd / 本地 YAML / xDS) |
core.lrucache |
core/lrucache.lua |
LRU 缓存,支持 TTL |
core.ctx |
core/ctx.lua |
请求上下文管理(tablepool 复用) |
core.etcd |
core/etcd.lua |
etcd 客户端封装 |
core.string |
core/string.lua |
字符串工具函数 |
core.id |
core/id.lua |
ID 生成器(支持雪花 ID) |
core.dns.client |
core/dns/ |
DNS 客户端 |
core.pubsub |
core/pubsub.lua |
发布/订阅抽象 |
core.event |
core/event.lua |
Worker 间事件系统 |
关键设计模式: 所有模块通过 require("apisix.core") 获取统一的 core 引用,避免散乱的依赖关系。
四、请求处理流程(最核心的链路)
当用户请求到达 APISIX 后,经过如下阶段(都在 apisix/init.lua 中定义):
第一阶段:http_access_phase() — 接入与路由匹配
1. HTTPS 客户端证书校验
2. Debug 动态调试检查
3. URI 规范化(尾部斜杠处理、servlet 路径处理)
4. X-Forwarded-* 请求头处理
5. Router 匹配 → 找到匹配的 Route
6. 无匹配 Route → 执行 Global Rules → 返回 404
7. 合并配置:
plugin_config_id → service_id → consumer → consumer_group
8. 执行 Global Rules
9. 有 script → 执行 script 脚本
10. 否则 → 过滤插件 → 依次执行 rewrite 阶段插件 → access 阶段插件
11. handle_upstream():
- 通过 upstream_id 或内联 upstream 获取上游配置
- 负载均衡器选择后端节点
- 执行 before_proxy 阶段
- 代理请求到上游
第二/三阶段:Header/Body 过滤
header_filter → 设置 Server 头、上游状态头 → 执行 header_filter 插件
body_filter → 执行 body_filter 插件 & delayed_body_filter 插件
第四阶段:http_log_phase() — 日志上报
完成 Tracing span → 执行 log 阶段插件 → 被动健康检查 → 释放 api_ctx
关键数据结构:api_ctx
每个请求会从 tablepool 分配一个 api_ctx 表,携带:
matched_route— 匹配到的路由upstream_conf— 上游配置plugins— 要执行的插件列表consumer— 消费者信息var— Nginx 变量快照
该表贯穿所有阶段,在 log 阶段结束时释放回 tablepool。
五、插件系统(apisix/plugin.lua + apisix/plugins/)
5.1 插件加载机制
apisix/plugin.lua 是插件引擎,核心函数:
load():读取配置的插件列表 → 逐个调用load_plugin()→ 按优先级降序排序load_plugin(name):require 插件模块 → 校验 priority/version/schema → 调用plugin.init()→ 注入_meta字段run_plugin(phase, ...):按阶段执行插件链filter_plugins(user_plugins, conf_version):根据 Route 配置筛选要执行的插件
5.2 插件接口规范
每个插件模块导出以下字段(以 apisix/plugins/example-plugin.lua 为参考):
local plugin_name = "example-plugin"
local _M = {
version = 0.1, -- 插件版本号(必填)
priority = 0, -- 执行优先级(必填,数字越大越先执行)
name = plugin_name, -- 插件名称
schema = {}, -- JSON Schema 定义(必填)
type = 'auth', -- 插件类型(选填,auth 类型有特殊处理)
}
生命周期钩子(均可选):
init()/destroy()— 加载/卸载时调用check_schema(conf, schema_type)— 自定义 schema 校验rewrite(conf, ctx)/access(conf, ctx)— 请求处理header_filter(conf, ctx)/body_filter(conf, ctx)— 响应处理delayed_body_filter(conf, ctx)— 延迟 body 过滤log(conf, ctx)— 日志上报api()/control_api()— 注册额外的 Admin/Control API
5.3 插件优先级体系
插件按 priority 降序执行,部分关键插件的优先级参考:
| 优先级范围 | 典型插件 | 说明 |
|---|---|---|
| 4000+ | ip-restriction, referer-restriction | 安全拦截类 |
| 3000-3999 | cors, csrf, fault-injection | 安全/测试类 |
| 2500-2999 | key-auth, jwt-auth, basic-auth | 认证类 |
| 1000-1999 | limit-count, limit-conn, limit-req | 限流类 |
| 500-999 | proxy-rewrite, response-rewrite | 重写类 |
| 1-499 | 日志插件, prometheus | 可观测类 |
5.4 插件分类速览
| 类别 | 代表插件 |
|---|---|
| 认证 | key-auth, jwt-auth, basic-auth, hmac-auth, openid-connect, forward-auth |
| 安全 | ip-restriction, ua-restriction, cors, csrf, uri-blocker, api-breaker |
| 限流 | limit-count, limit-conn, limit-req, traffic-split |
| 重写 | proxy-rewrite, redirect, response-rewrite, proxy-mirror |
| Serverless | serverless-pre-function, serverless-post-function |
| AI | ai-proxy, ai-prompt-decorator, ai-prompt-guard, ai-rag, ai-rate-limiting |
| 日志 | kafka-logger, http-logger, syslog, elasticsearch-logger, loki-logger 等 |
| 可观测 | prometheus, zipkin, skywalking, opentelemetry, datadog |
| 集成 | aws-lambda, azure-functions, grpc-transcode, grpc-web, dubbo-proxy |
六、Admin API 与 CRUD 体系(apisix/admin/)
6.1 架构
HTTP 请求 → admin/init.lua(Token 认证 + 路由分发)→ resource.lua(通用 CRUD)→ etcd
apisix/admin/init.lua 中定义了资源到处理模块的映射:
| 资源 | 处理模块 | 对应用途 |
|---|---|---|
| routes | admin/routes.lua | 路由管理 |
| services | admin/services.lua | 服务管理 |
| upstreams | admin/upstreams.lua | 上游管理 |
| consumers | admin/consumers.lua | 消费者管理 |
| ssls | admin/ssl.lua | SSL 证书管理 |
| global_rules | admin/global_rules.lua | 全局规则 |
| plugin_configs | admin/plugin_config.lua | 插件配置复用 |
| stream_routes | admin/stream_routes.lua | 四层路由 |
| secrets | admin/secrets.lua | 密钥管理 |
6.2 通用 CRUD 模式(admin/resource.lua)
这是一个经典的模板方法模式。每个资源模块通过 resource.new({...}) 创建,自动获得 GET/PUT/POST/DELETE/PATCH 的标准实现。具体每个资源的差异通过 schema、validator、id_schema 等配置项注入。
七、路由系统(apisix/router.lua + apisix/http/router/)
7.1 路由实现
APISIX 支持 3 种 HTTP 路由实现(基于 lua-resty-radixtree):
| 实现 | 匹配依据 | 文件 |
|---|---|---|
radixtree_uri |
仅 URI | http/router/radixtree_uri.lua |
radixtree_host_uri |
Host + URI | http/router/radixtree_host_uri.lua |
radixtree_uri_with_parameter |
URI + 参数 | http/router/radixtree_uri_with_parameter.lua |
此外还有:
- SSL 路由:
ssl/router/radixtree_sni.lua(基于 SNI 匹配) - Stream 路由:基于 IP:Port 匹配
7.2 Route → Service → Upstream 的层级关系
Route ──可选引用──→ Service ──可选引用──→ Upstream
│ │ │
└── 定义 URI/Host └── 共享公共配置 └── 后端节点池
匹配规则 (plugins等) (负载均衡配置)
配置合并顺序:plugin_config → consumer → consumer_group → route → service
八、负载均衡(apisix/balancer.lua + apisix/balancer/)
balancer.lua 是负载均衡的调度中心,负责在请求处理时创建 balancer 对象并选择合适的后端节点。
支持的算法(apisix/balancer/):
roundrobin.lua— 加权轮询chash.lua— 一致性哈希ewma.lua— 指数加权移动平均(最小延迟算法)least_conn.lua— 最小连接数priority.lua— 优先级
九、配置管理与热更新
9.1 配置提供者抽象
APISIX 支持三种配置来源,通过 config.yaml 中的 config_provider 切换:
- etcd(
core/config_etcd.lua):默认模式,通过 etcd watch 实现实时热更新 - yaml(
core/config_yaml.lua):独立模式,从本地 YAML/JSON 文件读取 - xDS(
core/config_xds.lua):对接 Envoy xDS 控制面
三种提供者实现同一接口:
init() → init_worker() → values(key) → conf_version()
9.2 etcd 热更新流程
etcd PUT /routes/xxx → core/config_etcd.lua watch 回调
→ 路由表重建 → 新请求使用新路由(无需 reload Nginx)
同理适用于 Service、Upstream、Plugin、SSL 证书等所有配置。
十、测试体系(t/)
APISIX 使用 Perl 版 Test::Nginx::Socket::Lua 作为测试框架。
启动文件:
t/APISIX.pm— 测试基础配置和辅助函数t/lib/— 测试辅助库
目录结构:
t/admin/— Admin API CRUD 测试(60+ 文件)t/plugin/— 插件测试(250+ 文件)t/core/— 核心模块测试(35+ 文件)t/cli/— CLI 测试t/stream-node/,t/stream-plugin/— 四层代理测试
测试用例结构示例:
use t::APISIX;
use Test::Nginx::Socket::Lua;
run_tests();
__DATA__
=== TEST 1: 测试描述
--- config
location /t {
content_by_lua_block {
-- 测试逻辑
}
}
--- response_body
期望的输出
--- no_error_log
[error]
十一、建议的阅读顺序
按照以下顺序阅读,可以逐步建立起对整个系统的完整认知:
第一阶段:骨架(建立全局观)
bin/apisix— 启动脚本,了解如何拉起 OpenRestyapisix/cli/apisix.lua+apisix/cli/ops.lua— CLI 命令处理,了解 init/start 等命令的实现apisix/init.lua— 主入口文件,重点关注http_init_worker()的初始化顺序和http_access_phase()的请求处理流程
第二阶段:核心模块(理解基础设施)
apisix/core.lua— 核心模块聚合入口,了解有哪些核心能力apisix/core/ctx.lua— 请求上下文,理解api_ctx的创建/释放机制apisix/core/config_etcd.lua— etcd 配置提供者,理解配置如何读取和热更新apisix/core/lrucache.lua— 缓存机制apisix/core/request.lua+apisix/core/response.lua— 请求/响应操作封装
第三阶段:核心引擎(理解关键链路)
apisix/router.lua+apisix/http/router/radixtree_uri.lua— 路由匹配机制apisix/plugin.lua— 插件引擎,理解插件加载、过滤、执行的生命周期apisix/upstream.lua+apisix/balancer.lua— 上游管理和负载均衡apisix/http/service.lua— Route → Service 的配置继承逻辑
第四阶段:Admin API(理解控制面)
apisix/admin/init.lua— Admin API 路由分发apisix/admin/resource.lua— 通用 CRUD 基类apisix/admin/routes.lua— 以 Route CRUD 为例,理解具体资源的实现方式
第五阶段:深入插件(实践出真知)
apisix/plugins/example-plugin.lua— 插件开发模板- 选择一个你感兴趣的简单插件深入阅读(推荐从
key-auth.lua或limit-count.lua开始) - 阅读
apisix/plugins/ai-proxy.lua— 了解复杂插件的结构和 AI 网关能力
第六阶段:扩展话题
apisix/stream/— 四层代理子系统apisix/discovery/— 服务发现(consul/nacos/eureka 等)apisix/secret/— 密钥管理t/— 测试编写,通过测试反向理解功能
十二、关键设计模式总结
| 模式 | 体现位置 | 说明 |
|---|---|---|
| 外观模式 | apisix/core.lua |
聚合所有核心子模块,统一访问入口 |
| 模板方法 | apisix/admin/resource.lua |
通用 CRUD 基类,子模块注入差异化配置 |
| 策略模式 | apisix/router.lua / apisix/balancer.lua |
可插拔的路由/负载均衡实现 |
| 插件生命周期 | apisix/plugin.lua + apisix/plugins/*.lua |
按优先级排序,分阶段执行 |
| 观察者模式 | apisix/core/config_etcd.lua 中的 etcd watch |
配置变更自动触发热更新 |
| 对象池模式 | tablepool + apisix/core/ctx.lua |
复用 api_ctx 表,减少 GC 压力 |
| 提供者抽象 | core/config_etcd.lua / core/config_yaml.lua / core/config_xds.lua |
统一的配置接口,可切换后端 |
十三、开发环境搭建(速查)
# 安装依赖
make deps
# 启动 APISIX
make run
# 停止
make stop
# 运行测试
make test
# 运行特定测试
prove -I t/ t/plugin/key-auth.t
# 代码风格检查
make lint
建议配合 Apache APISIX 官方文档 和源码中的注释一起阅读。遇到问题时,
t/目录下的测试用例是理解各项功能的最佳参考资料。