APISIX自定义插件开发全指南:从零到部署的完整流程

APISIX自定义插件开发全指南:从零到部署的完整流程

一、插件开发核心价值与场景

APISIX作为云原生API网关,其插件机制是功能扩展的核心。自定义插件能解决三大类问题:业务定制化逻辑(如特定鉴权规则)、性能优化(如自定义缓存策略)、协议扩展(如支持私有RPC协议)。相较于修改核心代码,插件开发具有隔离性强、热加载、版本可控等优势。

典型应用场景包括:

  • 实现企业级SSO集成
  • 开发专用流量染色模块
  • 构建自定义限流算法
  • 对接私有监控系统

二、插件开发环境准备

2.1 开发工具链配置

  1. OpenResty环境:APISIX基于OpenResty,需安装1.17+版本

    1. # Ubuntu示例安装
    2. sudo apt install -y libpcre3-dev libssl-dev zlib1g-dev
    3. wget https://openresty.org/download/openresty-1.21.4.1.tar.gz
    4. tar zxvf openresty-*.tar.gz
    5. cd openresty-*
    6. ./configure --prefix=/usr/local/openresty
    7. make && make install
  2. APISIX源码获取

    1. git clone https://github.com/apache/apisix.git
    2. cd apisix
    3. make deps # 安装依赖
  3. 开发工具推荐

    • ZeroBrane Studio(Lua调试)
    • VS Code + Lua插件
    • Postman(API测试)

2.2 调试环境搭建

建议使用apisix-docker快速启动测试环境:

  1. docker run -d --name apisix \
  2. -p 9080:9080 -p 9443:9443 \
  3. -v $(pwd)/conf:/usr/local/apisix/conf \
  4. apache/apisix:3.0.0

三、插件开发全流程解析

3.1 插件目录结构规范

标准插件应包含以下文件:

  1. /apisix/plugins/your-plugin/
  2. ├── handler.lua # 主逻辑
  3. ├── schema.lua # 配置校验
  4. ├── access.lua # 访问阶段逻辑(可选)
  5. ├── header_filter.lua # 头部处理(可选)
  6. ├── body_filter.lua # 响应体处理(可选)
  7. ├── log.lua # 日志阶段(可选)
  8. └── api/ # 管理API(可选)
  9. └── v1/
  10. └── routes.lua # 插件配置API

3.2 核心开发步骤

3.2.1 插件基础结构

  1. -- handler.lua 示例
  2. local plugin_name = "your-plugin"
  3. local schema = require("apisix.plugins." .. plugin_name .. ".schema")
  4. local _M = {
  5. version = 0.1,
  6. priority = 1000,
  7. name = plugin_name,
  8. schema = schema.schema,
  9. }
  10. function _M.check_schema(conf)
  11. return core.schema.check(schema.schema, conf)
  12. end
  13. function _M.access(conf, ctx)
  14. -- 访问阶段逻辑
  15. ngx.log(ngx.INFO, "plugin executed with conf: ", core.json.encode(conf))
  16. end
  17. return _M

3.2.2 插件生命周期管理

APISIX插件执行包含6个阶段:

  1. init:服务启动时初始化
  2. init_worker:每个worker进程启动时执行
  3. rewrite:请求重写阶段
  4. access:访问控制阶段(核心逻辑常在此实现)
  5. header_filter:响应头处理
  6. body_filter:响应体处理
  7. log:日志记录阶段

3.2.3 配置校验实现

  1. -- schema.lua 示例
  2. local core = require("apisix.core")
  3. local schema = {
  4. type = "object",
  5. properties = {
  6. enable = {type = "boolean", default = true},
  7. threshold = {type = "number", minimum = 0},
  8. endpoints = {
  9. type = "array",
  10. items = {type = "string", format = "uri"},
  11. minItems = 1
  12. }
  13. },
  14. required = {"endpoints"}
  15. }
  16. return {schema = schema}

3.3 高级功能实现

3.3.1 依赖注入模式

  1. -- 使用core.config.local_conf获取全局配置
  2. local config = core.config.local_conf()
  3. local redis_host = config.plugin_attr.your_plugin.redis_host or "127.0.0.1"
  4. local redis = require("resty.redis")
  5. local red = redis:new()
  6. red:set_timeout(1000)

3.3.2 异步处理实现

  1. -- 使用ngx.thread实现非阻塞IO
  2. local ok, err = ngx.thread.spawn(function(conf)
  3. -- 异步任务逻辑
  4. local res = ngx.location.capture("/internal/check", {
  5. method = ngx.HTTP_POST,
  6. body = core.json.encode(conf)
  7. })
  8. return res.body
  9. end, conf)

四、插件测试与调试

4.1 单元测试实践

  1. -- t/plugin/your-plugin.lua 示例
  2. local core = require("apisix.core")
  3. local plugin = require("apisix.plugins.your-plugin")
  4. describe("Plugin your-plugin", function()
  5. it("should validate correct config", function()
  6. local conf = {enable = true, threshold = 10}
  7. local ok, err = plugin.check_schema(conf)
  8. assert.True(ok)
  9. end)
  10. it("should reject invalid config", function()
  11. local conf = {enable = "yes"} -- 类型错误
  12. local ok, err = plugin.check_schema(conf)
  13. assert.False(ok)
  14. assert.not_nil(err)
  15. end)
  16. end)

4.2 集成测试方法

  1. 使用test_nginx框架:

    1. prove -I./t/lib t/plugin/your-plugin.t
  2. 端到端测试

    1. # 启动测试环境
    2. APISIX_LISTEN=9081 make run
    3. # 执行测试请求
    4. curl -X POST http://127.0.0.1:9081/apisix/admin/routes/1 \
    5. -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
    6. -d '{
    7. "uri": "/test",
    8. "plugins": {
    9. "your-plugin": {
    10. "enable": true,
    11. "threshold": 5
    12. }
    13. },
    14. "upstream": {
    15. "type": "roundrobin",
    16. "nodes": {"127.0.0.1:1980": 1}
    17. }
    18. }'

五、插件部署与运维

5.1 生产部署流程

  1. 编译打包

    1. # 在APISIX根目录执行
    2. make build-plugins PLUGINS=your-plugin
  2. 配置更新

    1. # conf/config.yaml
    2. plugins:
    3. - your-plugin
  3. 动态加载

    1. curl http://127.0.0.1:9180/apisix/admin/plugin_metadata/your-plugin \
    2. -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
    3. -X PUT -d '{"version":"1.0"}'

5.2 监控与调优

  1. 性能指标采集

    1. -- log阶段添加指标
    2. local prometheus = require("apisix.plugins.prometheus")
    3. prometheus.counter("plugin_your_plugin_requests_total", 1, {plugin="your-plugin"})
  2. 日志分析建议

    • 关键操作记录ngx.INFO级别日志
    • 错误情况使用ngx.ERR级别
    • 避免在热路径中记录大量日志

六、最佳实践与避坑指南

6.1 性能优化技巧

  1. 缓存策略

    1. local cache = core.cache.new("your-plugin_cache", {
    2. ttl = 60, -- 1分钟缓存
    3. negative_ttl = 10
    4. })
  2. 批处理设计

    1. -- 使用ngx.shared.DICT实现跨请求共享数据
    2. local dict = ngx.shared.your_plugin_dict
    3. local batch_data = dict:get("batch_data") or {}
    4. table.insert(batch_data, ctx.var.request_id)

6.2 常见问题解决方案

  1. 插件不生效

    • 检查conf/config.yaml是否包含插件
    • 验证路由配置是否正确
    • 检查nginx.conf是否包含lua_package_path
  2. 内存泄漏排查

    1. # 使用nginx -T查看完整配置
    2. nginx -T | grep your_plugin
    3. # 检查共享内存使用情况
    4. curl http://127.0.0.1:9091/nginx_status

七、进阶开发方向

  1. WASM插件支持:APISIX 3.0+支持通过WASM扩展
  2. gRPC插件开发:使用apisix.stream.grpc模块
  3. 多语言插件:通过Sidecar模式实现Java/Go插件

结语

自定义插件开发是APISIX生态扩展的核心能力。通过遵循本文介绍的规范流程,开发者可以高效构建出稳定、高性能的插件。建议从简单功能开始实践,逐步掌握插件生命周期管理、配置校验、性能优化等高级技巧。实际开发中应特别注意错误处理和资源释放,确保插件在生产环境稳定运行。