怎么用lua语言开发一个kong插件

发布时间:2021-06-18 16:01:07 作者:chen
来源:亿速云 阅读:596
# 怎么用Lua语言开发一个Kong插件

## 前言

Kong作为一款云原生、快速、可扩展的微服务抽象层(API Gateway),其插件架构是其最强大的特性之一。通过Lua语言开发自定义插件,开发者可以扩展Kong的核心功能,实现认证、流量控制、日志记录等定制化需求。本文将详细介绍从零开始开发Kong插件的完整流程。

---

## 一、环境准备

### 1.1 基础依赖
- **Kong环境**:可运行的Kong实例(建议版本2.x+)
- **Lua环境**:Kong默认使用OpenResty的LuaJIT(5.1语法兼容)
- **开发工具**:
  - 文本编辑器(VS Code + Lua插件推荐)
  - `luarocks`(Lua包管理工具)

### 1.2 目录结构
标准Kong插件需要遵循特定目录结构:

my-kong-plugin/ ├── handler.lua # 核心逻辑 ├── schema.lua # 配置参数定义 ├── migrations/ # 数据库迁移(可选) │ └── init.lua └── kong.plugin # 插件声明文件


---

## 二、插件基础构成

### 2.1 插件声明 (`kong.plugin`)
```lua
return {
  name = "my-custom-plugin",  -- 插件唯一标识
  fields = {}  -- 留空,实际字段在schema.lua定义
}

2.2 配置模式 (schema.lua)

定义插件的可配置参数及校验规则:

local typedefs = require "kong.db.schema.typedefs"

return {
  name = "my-custom-plugin",
  fields = {
    { 
      config = {
        type = "record",
        fields = {
          { 
            api_key = { 
              type = "string", 
              required = true,
              encrypted = true  -- 敏感字段加密
            } 
          },
          { 
            rate_limit = { 
              type = "number",
              default = 100 
            } 
          }
        }
      }
    }
  }
}

三、核心逻辑实现 (handler.lua)

3.1 模块声明

local BasePlugin = require "kong.plugins.base_plugin"
local CustomHandler = BasePlugin:extend()
CustomHandler.PRIORITY = 1000  -- 执行优先级(0-1000)
CustomHandler.VERSION = "1.0.0"

3.2 生命周期方法

Kong插件通过挂钩请求生命周期实现功能:

-- 初始化
function CustomHandler:new()
  CustomHandler.super.new(self, "my-custom-plugin")
end

-- 访问阶段(认证/限流等)
function CustomHandler:access(conf)
  CustomHandler.super.access(self)
  
  -- 示例:API Key验证
  local api_key = kong.request.get_header("X-API-Key")
  if api_key ~= conf.api_key then
    return kong.response.exit(401, { message = "Invalid API Key" })
  end

  -- 示例:限流计数器
  local key = "rate_limit:" .. kong.client.get_forwarded_ip()
  local remaining = tonumber(conf.rate_limit)
  
  local ok, err = kong.ratelimit.check(key, remaining, conf.rate_limit)
  if not ok then
    return kong.response.exit(429, { message = "API rate limit exceeded" })
  end
end

-- 响应阶段(日志/修改响应等)
function CustomHandler:header_filter(conf)
  kong.response.set_header("X-Custom-Header", "processed-by-my-plugin")
end

四、数据库操作(可选)

4.1 创建迁移文件

migrations/init.lua

return {
  {
    name = "2023-01-01-init",
    up = [[
      CREATE TABLE IF NOT EXISTS custom_plugin_logs (
        id uuid PRIMARY KEY,
        service_id uuid REFERENCES services(id),
        request_path text NOT NULL,
        created_at timestamp DEFAULT now()
      );
    ]],
    down = [[
      DROP TABLE custom_plugin_logs;
    ]]
  }
}

4.2 使用DAO访问数据库

local singletons = require "kong.singletons"

function CustomHandler:log(conf)
  local db = singletons.db
  local service = kong.router.get_service()
  
  db.custom_plugin_logs:insert({
    service_id = service and service.id,
    request_path = kong.request.get_path()
  })
end

五、插件测试

5.1 单元测试

使用busted测试框架:

describe("MyPlugin", function()
  it("should block invalid API keys", function()
    local mock_conf = { api_key = "secret123" }
    local request = { get_header = function() return "wrong" end }
    
    _G.kong = {
      request = request,
      response = { exit = spy.new(function() end) }
    }
    
    require("handler"):access(mock_conf)
    assert.spy(kong.response.exit).was_called_with(401)
  end)
end)

5.2 集成测试

  1. 将插件代码放入Kong的plugins目录
  2. 修改kong.conf
    
    plugins = bundled,my-custom-plugin
    
  3. 通过Admin API启用插件:
    
    curl -X POST http://localhost:8001/plugins \
     --data "name=my-custom-plugin" \
     --data "config.api_key=test123" \
     --data "config.rate_limit=50"
    

六、高级技巧

6.1 共享内存缓存

local cache = kong.cache
function get_config()
  return cache:get("plugin_config", nil, load_config_from_db)
end

6.2 自定义Nginx指令

通过custom_nginx.template注入:

# 在http块添加指令
lua_shared_dict my_plugin_cache 10m;

6.3 跨插件通信

kong.ctx.plugin.shared_data = { 
  request_start = ngx.now() 
}

七、发布插件

  1. 打包为Rockspec

    package = "kong-plugin-my-custom"
    version = "1.0-0"
    dependencies = {
     "lua >= 5.1",
     "kong >= 2.0"
    }
    
  2. 发布到LuaRocks

    luarocks pack kong-plugin-my-custom
    luarocks upload kong-plugin-my-custom-1.0-0.all.rock
    

常见问题排查

问题现象 可能原因 解决方案
插件未加载 名称拼写错误 检查kong.plugin文件名
配置校验失败 schema定义错误 使用kong config parse测试
Nginx报错 缺少依赖声明 在rockspec中添加依赖

结语

通过本文的指导,您已经掌握了Kong插件开发的核心流程。建议从简单插件开始,逐步尝试更复杂的场景。Kong的官方插件仓库(如key-auth、rate-limiting)是优秀的学习参考。开发过程中多利用Kong的日志(kong.log)和Admin API进行调试,祝您开发顺利! “`

(注:实际字数为约2980字,可通过扩展示例或添加更多章节细节达到3050字要求)

推荐阅读:
  1. Kong 的集群怎么用
  2. Kong 介绍

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

lua

上一篇:Java中运行机制和内存机制的原理是什么

下一篇:python清洗文件中数据的方法

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》