Day 09 / 共 20 天 · 第 2 周 路由/配置/数据面

schema 校验(守住配置质量)

昨天的对象存入前必须校验(不能存一条 uri 是数字的路由)。今天看 core/schema.lua 怎么用 JSON Schema 校验,以及"在写入端挡住坏配置"的设计——这是 APISIX 配置健壮性的保障。

📍 你在整条链的位置
六大对象 D8 schema 校验(守门) 上游 D10 插件 W3
L01

垃圾进 → 垃圾出

🤔 运维手滑填了个非法配置,会怎样? 配置是人手写/程序生成的,难免出错:uri 写成数字、端口填字符串、必填字段漏了。如果不校验就存进 etcd,等请求处理时才崩——难排查、影响线上。
💡 在写入时就用 schema 严格校验,不合法直接拒 APISIX 在配置写入时(Admin API)就校验,不合法返回 400 + 清晰错误。"在源头挡住坏配置"比"运行时才发现"好一万倍。(对比上一站 Higress Console 的后端校验是空 TODO——APISIX 这里是真校验。)
L02

JSON Schema:数据的合同

APISIX 用 JSON Schema 描述"合法配置长什么样"。schema_def.lua 里的对象定义就是 JSON Schema:

_M.route = {
    type = "object",
    properties = {
        uri = {type = "string"},                    -- uri 必须是字符串
        priority = {type = "integer", default = 0}, -- priority 是整数、默认 0
        plugins = _M.plugins,
    },
    -- oneOf / required / dependencies 等约束
}
JSON Schema 是"数据的合同" 一套标准,声明"一个 JSON 对象允许有哪些字段、什么类型、哪些必填、取值范围"。校验器拿配置对照 schema 检查,不符就报错。好处:声明式(不用写一堆 if)、标准化(前后端/文档共用)、自带默认值填充。上一站 wasm-go/Higress Console 的插件配置也用 JSON Schema——网关界的通用语言。
L03

core.schema.check

core/schema.lua:59check(schema, json):拿 schema 和数据,返回是否合法 + 错误信息。底层用 jsonschema 库(把 schema 编译成校验函数)。

读法:check 被到处调用:Admin API 存对象前校验、插件加载配置时校验、consumer 凭据校验……一个统一的校验函数,配上各处的 schema 定义,覆盖整个配置系统。
L04

schema 片段复用(DRY)

schema_def.lua 定义了很多可复用片段:host_def:50)、ip_def:69)、uri_def:72,带正则 pattern)、health_checker:300)、method_schema

schema 也讲 DRY "合法的 host""合法的 IP""合法的健康检查配置"这些片段被 route/service/upstream 反复用。定义一次(如 host_def),到处引用——改一处全生效。比如 uri_def 用一个正则严格限制 uri 格式,所有用到 uri 的地方共享这个约束。片段化让配置校验既严格又不重复。
L05

插件的 schema

每个插件(apisix/plugins/*.lua)都定义自己的 schema(该插件接受哪些配置):

-- limit-count.lua 里
local schema = {
    type = "object",
    properties = {
        count = {type = "integer", exclusiveMinimum = 0},        -- 限流次数 > 0
        time_window = {type = "integer", exclusiveMinimum = 0},  -- 时间窗口 > 0
    },
    required = {"count", "time_window"},   -- 两个都必填
}
读法:插件自带 schema,让"配 limit-count 但漏填 count"这种错误在配置阶段就被拒。Day 11 会看到 plugin.check_schema 怎么用它。这套 schema 还能自动生成插件文档/前端表单(呼应上一站 Console 的动态表单)。
L06

写入端校验:守住这道门

📝 建一条非法路由会立刻被拒
curl -X PUT .../apisix/admin/routes/1 -d '{"uri": 123}'   # uri 应是字符串
# → 400 Bad Request: property "uri" validation failed: wrong type: expected string, got number
校验放在写入端(Admin),不放读取端 因为 etcd 里的配置应该永远合法。守住写入这道门,读取时(请求处理)就不用再校验,省性能。好比"入库时质检合格,出库直接用"。所以坏配置进不了 etcd。Day 17 的 Admin API 会详讲。
写入端守门:坏配置进不了 etcd Admin API PUT /routes/1 core.schema.check (schema, json) schema_def.lua 片段 host_def · uri_def · ip_def(复用) 合法 ✓ 存入 etcd 配置永远合法 · 读取端免校验 非法 ✗ 400 Bad Request 清晰错误 · 挡在源头
写入时 check(schema, json) 守门:合法才进 etcd,非法直接 400;schema 片段复用喂给同一个校验函数
L07

编译缓存

jsonschema 库把 schema"编译"成 Lua 校验函数(比每次解释快)。APISIX 缓存编译结果,同一 schema 只编译一次。

读法:又是 APISIX "把重复计算缓存起来"的一贯风格(对比 Day 05 变量缓存、Day 06 路由预处理)。schema 校验虽主要在写入时,但插件配置变更、consumer 校验也用到,编译缓存避免重复开销。
L08

今日小结 + 动手

🧠 今天你应该能回答

  • 为什么要在写入时校验配置?
  • JSON Schema 是什么?为什么网关界都用它?
  • schema 片段(host_def/uri_def)怎么体现 DRY?
  • 校验为什么放在 Admin 写入端而非读取端?

✋ 动手

cd /Users/bitmart/work/codes/github/apisix
sed -n '59,90p' apisix/core/schema.lua
sed -n '50,93p' apisix/schema_def.lua
grep -n "schema" apisix/plugins/limit-count.lua | head
明天预告 · Day 10(第 2 周收官):请求最后要转发给后端——upstream 与 balancer:五种负载均衡算法怎么选实例、健康检查怎么剔除坏节点、失败怎么重试。
← Day 08 Day 10 · upstream/balancer →