十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Apache APISIX External Plugin 外部插件与 Plugin Runner 开发接入全指南

Apache APISIX External Plugin 外部插件与 Plugin Runner 开发接入全指南 API网关后端云原生微服务【免费下载链接】apisixThe Cloud-Native API Gateway and AI Gateway项目地址https://gitcode.com/gh_mirrors/api/apisix点击查看免费下载导读本指南围绕 Apache APISIX 的External Plugin外部插件与Plugin Runner插件运行器机制展开讲解为什么需要它、它是如何工作的、如何实现、如何在生产与开发两种场景下配置以及常见问题的解决方案。读完本文你将掌握用 Java / Go / Python / JavaScript 等任意语言编写 APISIX 插件并接入运行的方法、ext-plugin-pre-req/ext-plugin-post-req/ext-plugin-post-resp三个外部插件入口的使用方式以及 Plugin Runner 进程生命周期管理、RPC 通信协议和降级degradation等底层原理可直接基于当前仓库落地实践。什么是 External Plugin 与 Plugin RunnerAPISIX 原生使用 Lua 语言编写插件这类插件在 APISIX 进程内部直接执行性能好、开发快。但在很多真实场景中团队可能希望复用已有的 Java / Go / Python / JavaScript 技术栈与生态而不是学习 Lua。为此APISIX 提供了一种Sidecar 模式APISIX 以子进程的方式加载并运行一个独立的进程这个进程就是Plugin Runner而由开发者用其他语言编写的、运行在 Runner 进程内的插件称为External Plugin外部插件。关键概念对应关系如下概念说明External Plugin由开发者用非 Lua 语言如 Java / Go / Python / JS编写的插件运行在独立的 Plugin Runner 进程中Plugin RunnerAPISIX 以子进程Sidecar方式管理的独立进程负责接收 APISIX 发来的 RPC 请求、执行外部插件并返回结果ext-plugin-*APISIX 侧用于把请求转发给 Plugin Runner 的内置插件包括ext-plugin-pre-req、ext-plugin-post-req、ext-plugin-post-resp三个在 APISIX 的路由配置中ext-plugin-*插件与其他任何 APISIX 插件一样可以被动态启用、禁用和重新配置无需重启 APISIX。从源码看这三个插件共享同一套 schema 与通信逻辑ext-plugin-pre-req.luapriority 12000在rewrite阶段执行请求处理调用RPC_HTTP_REQ_CALLext-plugin-post-req.luapriority -3000在access阶段执行请求处理同样是RPC_HTTP_REQ_CALLext-plugin-post-resp.luapriority -4000在before_proxy阶段执行响应处理调用RPC_HTTP_RESP_CALL。三个插件共用的 schema 定义在 apisix/plugins/ext-plugin/init.lualocal schema { type object, properties { conf { type array, items { type object, properties { name { type string, maxLength 128, minLength 1 }, value { type string, }, }, required {name, value} }, minItems 1, }, allow_degradation {type boolean, default false} }, }也就是说每个ext-plugin-*插件可以携带一个conf数组插件名称与参数键值对用于告诉 Plugin Runner 该调用哪些外部插件及传入哪些配置以及可选的allow_degradation允许降级默认为false。它是如何工作的整体工作流程如下在 APISIX 的config.yaml中配置ext-plugin.cmdAPISIX 将以此命令以子进程方式启动 Plugin Runner该子进程与 APISIX 主进程运行在同一系统用户下当 APISIX 重启或 reload 时Plugin Runner 也会随之重启当你为某个路由配置了ext-plugin-*插件后匹配该路由的请求会触发一次从 APISIX 到 Plugin Runner 的 RPC 调用Plugin Runner 收到 RPC 调用后在自身进程内构造一个请求上下文依次执行所配置的外部插件最后把处理结果返回给 APISIX外部插件及其执行顺序由ext-plugin-*插件中的conf数组决定且可以像普通插件一样动态调整。进程管理与守护逻辑从 apisix/plugins/ext-plugin/init.lua 的源码可以看到 Runner 进程的完整管理机制启动_M.init_worker()在privileged agent进程中读取ext-plugin.cmd配置若存在则调用setup_runner(cmd)通过ngx_pipe.spawn启动子进程见 init.lua 第 986-1005 行环境变量注入启动前会强制设置两个环境变量——APISIX_CONF_EXPIRE_TIME配置令牌过期时间与APISIX_LISTEN_ADDRESSUnix Socket 监听地址见 spawn_proc守护重启Runner 异常退出后setup_runner会通过runner:wait()捕获退出事件向events_list广播runner_exit事件触发配置令牌缓存清理并在3 秒后自动重新拉起Runner见 init.lua 第 936-983 行退出清理_M.exit_worker()在退出阶段对 Runner 先发送SIGTERM并调用core.os.waitpid(pid, 1)等待 1 秒让其清理资源随后由 GC 终结器兜底发送SIGKILL见 init.lua 第 1008-1022 行。底层 RPC 通信协议APISIX 与 Plugin Runner 之间通过Unix Domain Socket 自定义二进制帧 FlatBuffers 序列化进行 RPC 通信核心实现集中在 apisix/plugins/ext-plugin/init.lua 与 apisix/plugins/ext-plugin/helper.lua。帧格式每个消息包由 4 字节头部 数据体组成。首字节为 RPC 类型如RPC_PREPARE_CONF、RPC_HTTP_REQ_CALL、RPC_HTTP_RESP_CALL、RPC_EXTRA_INFO、RPC_ERROR后 3 字节为大端序的长度字段最大单包数据长度为2^24 - 1。发送与接收分别由send与receive函数实现见 init.lua 第 128-208 行。连接管理每个 worker 与 Runner 建立 TCP socket 连接settimeouts(1000, 60000, 60000)通信完成后调用setkeepalive(180 * 1000, 32)将连接放回连接池复用见 rpc_call。关键 RPC 流程RPC_PREPARE_CONF配置准备当某个路由首次命中ext-plugin-*时APISIX 会向 Runner 发送该请求对应的插件配置conf数组Runner 校验后返回一个conf token。token 会被缓存在ext-plugin共享字典shared dict与 Lua 侧 lrucache 中默认缓存 3600 秒见 helper.lua 的 get_conf_token_cache_time后续请求直接携带 token 而无需重复全量下发配置RPC_HTTP_REQ_CALL请求调用APISIX 将请求的 URI、args、headers、method、源 IP 等打包发送给 RunnerRunner 运行外部插件后返回动作结果。动作类型包括Stop直接终止请求由 APISIX 返回插件指定的状态码与响应体状态码缺省时默认 200Rewrite修改请求的 path、headers、query args甚至替换请求体RespHeaders直接改写响应头。RPC_EXTRA_INFO附加信息拉取Runner 处理过程中如需读取 Nginx 变量Var、请求体ReqBody或响应体RespBody可通过该 RPC 向 APISIX 拉取对应实现为 handle_extra_infoRPC_HTTP_RESP_CALL响应调用由ext-plugin-post-resp使用。before_proxy阶段先向上游发起一次真实请求拿到响应再把响应状态、响应头传给 Runner 做后处理Runner 可返回新的状态码与响应体。Socket 地址的确定helper.get_path()优先读取本地配置中的ext-plugin.path_for_test若配置则以unix:前缀拼接否则动态生成./conf/apisix-master_pid.sock的绝对路径见 helper.lua 第 30-51 行。超时重试与降级_M.communicate()封装了 RPC 调用的统一入口见 init.lua 第 873-907 行每次调用最多重试3 次若失败原因包含conf token not found会先刷新缓存recreate_lrucache会 flush 共享字典与 lrucache后重试当配置了allow_degradation true时Runner 异常会记录告警并放行请求降级为正常转发未配置时直接返回503 Service Unavailable。它是如何实现的如果你对 Plugin Runner 的内部实现例如 Runner 侧如何解析 FlatBuffers 协议、如何注册外部插件、Java / Go 版本的对象模型与线程模型感兴趣请参阅 Plugin Runner 实现文档。仓库内针对 ext-plugin 的协议客户端测试也提供了很好的实现参考例如 t/plugin/ext-plugin/sanity.t进程管理与 socket 通信冒烟测试、t/plugin/ext-plugin/http-req-call.t、t/plugin/ext-plugin/conf_token.t、t/plugin/ext-plugin/extra-info.t、t/plugin/ext-plugin/request-body.t、t/plugin/ext-plugin/response.t。支持的 Plugin Runner官方及社区提供的 Plugin Runner 实现如下Javaapache/apisix-java-plugin-runnerGoapache/apisix-go-plugin-runnerPythonapache/apisix-python-plugin-runnerJavaScriptzenozeng/apisix-javascript-plugin-runner这些 Runner 均实现了与 APISIX 的 RPC 协议你只需按其 README 编写插件并构建出可执行文件再按下一节的步骤接入 APISIX。在 APISIX 中配置 Plugin Runner生产环境由 APISIX 托管 Runner在生产环境把 Runner 的可执行文件路径配置到conf/config.yaml中APISIX 将以子进程方式管理该 Runnerext-plugin: cmd: [blah] # 替换为实际 Runner 可执行文件及参数例如 Go Runner 的二进制路径配置说明cmd是一个字符串数组第一个元素是 Runner 可执行文件的路径后续元素为其启动参数APISIX 启动时会在 privileged agent 进程中拉起该子进程并负责其生命周期重启、守护、退出清理生产环境下不要配置path_for_test此时 APISIX 会自动生成监听地址./conf/apisix-master_pid.sock无需手工指定。注意在 Mac 上APISIXv2.6版本无法管理该 Plugin Runner该限制在后续版本中已解决请以你所使用版本的官方说明为准。在 conf/config.yaml.example 中也给出了默认注释示例# ext-plugin: # cmd: [ls, -l]同时ext-plugin-pre-reqpriority: 12000、ext-plugin-post-reqpriority: -3000、ext-plugin-post-resppriority: -4000三个插件已默认列入启用插件列表见 conf/config.yaml.example 第 552 行与第 662-663 行。开发环境独立运行 Runner开发过程中我们希望单独运行 Plugin Runner这样可以只重启 Runner 而无需重启整个 APISIX。通过指定环境变量APISIX_LISTEN_ADDRESS可以让 Plugin Runner 监听一个固定地址例如APISIX_LISTEN_ADDRESSunix:/tmp/x.sock此时 Plugin Runner 将监听/tmp/x.sock。同时需要配置 APISIX 把 RPC 请求发送到这个固定地址注意path_for_test的值不带unix:前缀ext-plugin: # cmd: [blah] # 不要配置可执行文件 path_for_test: /tmp/x.sock # 不带 unix: 前缀开发模式配置要点必须注释掉cmd否则 APISIX 会再次托管拉起一个 Runner与手工启动的实例冲突path_for_test指定 APISIX 连接 Runner 的固定 socket 路径生产环境不应使用path_for_test此时监听地址由 APISIX 动态生成。在路由上启用外部插件完成 Runner 配置后即可像普通插件一样通过 Admin API 为路由配置外部插件。例如curl http://127.0.0.1:9180/apisix/admin/routes/1 -X PUT -d { uri: /hello, plugins: { ext-plugin-pre-req: { conf: [ {name: my-echo, value: bar} ] } }, upstream: { type: roundrobin, nodes: {127.0.0.1:1980: 1} } }其中conf数组中的name是 Runner 内已注册的外部插件名value是传给该插件的配置字符串具体解析方式由 Runner 侧插件决定。执行顺序即conf数组的顺序。外部插件支持动态启用、重新配置无需重启 APISIX。常见问题FAQPlugin Runner 由 APISIX 管理时无法访问我的环境变量自 APISIXv2.7起APISIX 可以将环境变量传递给 Plugin Runner。但默认情况下 Nginx 会隐藏所有环境变量因此需要先在conf/config.yaml中显式声明要透传的变量nginx_config: envs: - MY_ENV_VAR在 conf/config.yaml.example 中同样可以看到nginx_config段用于声明需要暴露给 Nginx/子进程的环境变量。若未声明Runner 子进程将看不到宿主机上的自定义环境变量。APISIX 使用 SIGKILL 终止 Plugin Runner而不是使用 SIGTERM自v2.7起当运行在 OpenResty 1.19 时APISIX 会改用SIGTERM来停止 Plugin Runner详见 exit_worker 的实现先runner:kill(SIGTERM)再core.os.waitpid(pid, 1)等待最多 1 秒。APISIX 需要等待 Plugin Runner 退出这样才能确保 Runner 持有的资源连接、临时文件等被充分释放。因此其策略是先发送SIGTERM给 Runner 1 秒时间优雅退出、清理资源若 1 秒后 Runner 仍在运行则发送SIGKILL强制终止。小结外部插件机制让 APISIX 摆脱了“只能用 Lua 写插件”的限制通过 Sidecar 形态的 Plugin Runner 与基于 Unix Socket FlatBuffers 的 RPC 协议把 Java、Go、Python、JavaScript 生态无缝接入 API 网关接入路径选择官方 Runner → 编写外部插件 → 配置ext-plugin.cmd生产或APISIX_LISTEN_ADDRESSpath_for_test开发→ 在路由上启用ext-plugin-*运行机制Runner 由 APISIX 以子进程托管并自动守护重启通信复用连接池配置令牌conf token缓存避免重复全量下发配置可靠性内置 3 次重试、令牌缓存刷新、allow_degradation降级放行以及先 SIGTERM 后 SIGKILL 的退出清理策略。无论是网关能力扩展还是团队技术栈复用外部插件机制都是 APISIX 生态中值得优先了解的高价值能力。赞分享API网关后端云原生微服务【免费下载链接】apisixThe Cloud-Native API Gateway and AI Gateway项目地址https://gitcode.com/gh_mirrors/api/apisix点击查看免费下载相关推荐APISIX External Plugin外部插件与 Plugin Runner 多语言插件开发指南APISIX External Plugin外部插件与 Plugin Runner 多语言插件开发指南 APISIX 的原生插件基于 Lua 编写并运行于网API网关后端云原生微服务Apache APISIX 外部插件External Plugin机制完全指南Plugin Runner 架构、配置与源码实现Apache APISIX 外部插件External Plugin机制完全指南Plugin Runner 架构、配置与源码实现 APISIX 官方文档后端微服务云原生APISIX 外部插件External Plugin与 Plugin Runner 完全指南跨语言插件开发、Sidecar 运行机制与生产配置APISIX 外部插件External Plugin与 Plugin Runner 完全指南跨语言插件开发、Sidecar 运行机制与生产配置 APISI后端微服务云原生创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表