ARTICLE DETAIL

资讯详情

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

Apache APISIX ext-plugin-post-resp 插件详解:在响应阶段运行外部插件

Apache APISIX ext-plugin-post-resp 插件详解:在响应阶段运行外部插件 Apache APISIX ext-plugin-post-resp 插件详解在响应阶段运行外部插件【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisixext-plugin-post-resp是 Apache APISIX 内置的ext-plugin-*系列插件之一用于在请求已从上游获取响应之后将响应交给 Plugin Runner 中运行的 External Plugin 处理实现用任意语言Go、Java、Python 等改写响应状态码、响应头和响应体。本文基于当前仓库的官方文档、插件源码与测试用例系统讲解该插件的工作机制、属性配置、启用与测试方法以及它与其他内置插件之间的兼容性边界帮助你在实际路由中安全、正确地落地响应阶段的外部插件能力。插件定位在响应阶段执行 External Plugin根据官方文档docs/zh/latest/plugins/ext-plugin-post-resp.md的描述ext-plugin-post-resp插件用于在执行内置 Lua 插件之前和在 Plugin Runner 内运行特定的 External Plugin并且在请求获取到上游的响应之后执行。这意味着它的核心职责是当 APISIX 已经拿到上游Upstream返回的 HTTP 响应时把这条响应的状态码、头部等信息通过 RPC 发送给 Plugin Runner由 External Plugin 对响应进行二次处理再把处理结果可能被修改过的状态码、响应头、响应体返回给客户端。External Plugin 执行的结果会直接影响当前请求的响应——这也是使用本插件时必须牢记的前提。在ext-plugin-*系列中三个插件的分工与执行时机互补插件优先级执行时机处理对象ext-plugin-pre-req12000请求进入 APISIX 后、请求被转发到上游前请求本身URI、请求头、请求体等ext-plugin-post-req-3000请求阶段access 阶段请求转发前的后续处理ext-plugin-post-resp-4000获取上游响应之后上游响应状态码、响应头、响应体优先级数值可在 conf/config.yaml.example 的plugins配置段中直接看到ext-plugin-post-req的优先级为-3000ext-plugin-post-resp的优先级为-4000。优先级越低表示越晚执行因此ext-plugin-post-resp是 APISIX 内置插件执行链上最靠后的插件之一。注意ext-plugin-post-resp处理的是上游响应而ext-plugin-pre-reqdocs/zh/latest/plugins/ext-plugin-pre-req.md处理的是客户端请求。两者配合可以分别实现请求改写与响应改写。工作原理直接向上游发起请求再把响应交给 Plugin Runner要理解ext-plugin-post-resp为什么能在获取上游响应之后执行需要看它的核心实现 apisix/plugins/ext-plugin-post-resp.lua。该插件在before_proxy阶段位于 access 阶段之后、正式代理转发之前通过lua-resty-http库主动向上游发起一次请求而不是走 APISIX 常规的代理转发管线。从源码看其处理流程大致如下建立到上游的连接get_response函数使用ctx.picked_server中的host与port、ctx.upstream_scheme中的协议通过http_obj:connect连接上游构造并发送请求URI 优先取ctx.var.upstream_uri若为空则回退到原始ctx.var.uri请求头来自core.request.headers(ctx)请求方法来自core.request.get_method()若存在请求体则一并携带拿到上游响应http_obj:request(params)返回响应对象res存入ctx.runner_ext_response通知 Plugin Runner 处理响应调用ext.communicate(conf, ctx, name, constants.RPC_HTTP_RESP_CALL)即通过 unix socket 与 Plugin Runner 进行RPC_HTTP_RESP_CALL类型的 RPC 交互把响应状态码和响应头发给 Runner并接收 Runner 可能改写后的状态码、响应头与响应体把结果写回客户端send_response函数根据 Runner 返回的结果ctx.runner_ext_response_body中的响应体分片或原始响应的body_reader通过ngx.print/ngx.flush直接向客户端输出。整个交互中如果向上游请求失败插件会关闭连接并返回502如果响应写出失败且响应头尚未发送也会返回502。External Plugin 与 Plugin Runner 的整体协作架构可参考官方文档 docs/zh/latest/external-plugin.md 中的架构图简单来说APISIX 以子进程方式拉起 Plugin RunnerRunner 与 APISIX 通过 unix socket 通信当某个路由启用了ext-plugin-*插件时命中该路由的请求会触发 APISIX 到 Runner 的 RPC 调用Runner 在其内部运行 External Plugin 并把结果返回给 APISIX。属性说明根据官方文档ext-plugin-post-resp支持以下两个属性名称类型必选项默认值有效值描述confarray否无[{name: ext-plugin-A, value: {\enable\:\feature\}}]在 Plugin Runner 内执行的插件列表配置allow_degradationboolean否false[false, true]当 Plugin Runner 临时不可用时是否允许请求继续设置为true时自动允许请求继续这两个属性的校验逻辑定义在 apisix/plugins/ext-plugin/init.lua 中ext-plugin-post-resp直接复用该共享 schemaschema ext.schema其中confarray类型至少包含 1 个元素minItems 1每个元素是一个对象包含两个必填字段——name字符串长度 1128 个字符和value字符串。value通常是一个 JSON 字符串用于向 External Plugin 传递其自身配置allow_degradationboolean类型默认值为false。从communicate的实现apisix/plugins/ext-plugin/init.lua可以看出allow_degradation的实际行为当 Plugin Runner 不可用时若allow_degradation为true则允许请求继续相当于降级为不处理响应否则直接返回503 Service Unavailable。该函数默认最多重试 3 次其中conf token not found错误会触发缓存刷新后重试其余错误直接终止并降级或返回 503。此外conf配置会被缓存在 APISIX 的共享内存ext-pluginshared dict与进程内 LRU 缓存中缓存有效期由 apisix/plugins/ext-plugin/helper.lua 中的get_conf_token_cache_time()决定当前为 3600 秒即 1 小时用于避免每个请求都向 Runner 重复发送RPC_PREPARE_CONF配置同步请求。使用限制与部分内置插件的兼容性边界官方文档明确提示启用本插件后APISIX 将使用lua-resty-http库向上游发起请求这会导致以下内置功能不可用proxy-control 插件不可用proxy-mirror 插件不可用proxy-cache 插件不可用APISIX 与上游间的双向认证mTLS功能尚不可用。这一限制的根因可以从源码结构推断ext-plugin-post-resp在before_proxy阶段用lua-resty-http直接向上游发起了独立请求并自行把响应写回客户端绕过了 APISIX 常规的代理proxy响应处理管线。因此那些挂接在代理管线上的插件如 proxy-cache 的缓存读写、proxy-mirror 的流量镜像、proxy-control 的响应控制以及依赖 APISIX 与上游之间 TLS 连接管理的 mTLS 能力都无法对这条旁路请求生效。在实际规划插件组合时应避免将上述插件与ext-plugin-post-resp同时用于同一条路由。前置准备配置 Plugin Runner在启用插件之前需要先让 APISIX 知道如何启动 Plugin Runner。在conf/config.yaml参考 conf/config.yaml.example中配置ext-plugin: cmd: [blah] # 替换为所选 Runner 的真实可执行命令如 Go/Java/Python RunnerAPISIX 会以子进程方式托管该 Plugin Runner当 APISIX 重启或重新加载时Runner 也会随之重启Runner 异常退出后APISIX 会在 3 秒后自动重新拉起见 apisix/plugins/ext-plugin/init.lua 中setup_runner的实现与runner_exit事件处理。开发调试场景下也可以让 Runner 单独运行并监听固定地址APISIX_LISTEN_ADDRESSunix:/tmp/x.sock同时在config.yaml中配置 APISIX 连接到该固定地址此时不要配置cmdext-plugin: path_for_test: /tmp/x.sock # 不带 unix: 前缀关于 Plugin Runner 的更多细节支持的 Runner 语言、环境变量传递、进程管理等请阅读 External Plugin 文档。启用插件以下示例展示了如何在指定路由中启用ext-plugin-post-resp插件来自官方文档。首先可以从config.yaml中获取admin_key并存入环境变量admin_key$(yq .deployment.admin.admin_key[0].key conf/config.yaml | sed s///g)然后通过 Admin API 创建路由并启用插件curl -i http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { uri: /index.html, plugins: { ext-plugin-post-resp: { conf : [ {name: ext-plugin-A, value: {\enable\:\feature\}} ] } }, upstream: { type: roundrobin, nodes: { 127.0.0.1:1980: 1 } } }其中conf数组中的每一项对应一个要执行的 External Pluginname是插件名value是传给该插件的配置JSON 字符串upstream指向实际后端服务此处示例为127.0.0.1:1980。同时确保plugins配置中已经启用ext-plugin-post-resp在 conf/config.yaml.example 中可见ext-plugin-post-resp位于插件列表且注释为priority: -4000。测试插件通过上述命令启用插件后可以使用如下命令测试插件是否生效curl -i http://127.0.0.1:9080/index.html在返回结果中可以看到刚刚配置的 Plugin Runner 已经被触发同时ext-plugin-A插件也已经被执行例如它可以在响应上追加自定义响应头或改写响应体。修改响应External Plugin 能对响应做什么从仓库测试用例 t/plugin/ext-plugin/response.t 可以验证ext-plugin-post-resp对上游响应的处理能力修改响应体测试modify_body场景下上游返回hello world经过 Runner 处理后客户端收到cat修改响应头测试modify_header场景下Runner 设置X-Runner: Test-Runner且可同时保留/过滤上游响应头modify same response headers场景验证了同名响应头的追加行为X-Same: one, two修改状态码测试modify_status场景下上游 200 响应被 Runner 改写为304容错行为default allow_degradation测试验证了默认配置下conf的传递与 Runner 不可用时的降级路径。这些能力的底层实现在 apisix/plugins/ext-plugin/init.lua 的RPC_HTTP_RESP_CALL处理器中APISIX 会把上游响应状态码和全部响应头发送给 RunnerRunner 返回的响应头会覆盖或追加到最终响应上同名头第一次出现用set_header重复出现用add_header若 Runner 未返回任何响应头则 APISIX 会保留上游响应头但会过滤掉一组禁止透传的头部包括connection、content-length、transfer-encoding、location、server、www-authenticate、content-encoding、content-type、content-location、content-language等见源码中的exclude_resp_header表若 Runner 返回了新的状态码非 0则用它覆盖上游状态码若 Runner 只改写了响应体而未指定状态码则沿用上游状态码。删除插件当你需要禁用ext-plugin-post-resp插件时可通过以下命令删除相应的 JSON 配置APISIX 会自动重新加载相关配置无需重启服务curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { uri: /index.html, upstream: { type: roundrobin, nodes: { 127.0.0.1:1980: 1 } } }即PUT 一个新的路由配置其中不再包含plugins.ext-plugin-post-resp字段。该操作与其他插件的删除方式一致均为声明式覆盖配置下发后立即生效。源码与测试指引如果你希望深入了解ext-plugin-post-resp的实现细节可以按以下路径继续阅读当前仓库apisix/plugins/ext-plugin-post-resp.lua插件主体包含before_proxy阶段的请求构造、RPC 交互与响应写出逻辑apisix/plugins/ext-plugin/init.lua共享 schema、unix socket RPC 收发、RPC_HTTP_RESP_CALL响应处理、communicate重试与降级逻辑apisix/plugins/ext-plugin/helper.luaunix socket 路径解析与 conf token 缓存时间apisix/plugins/ext-plugin-post-req.lua同系列ext-plugin-post-req插件实现便于对比执行时机t/plugin/ext-plugin/response.t响应改写体/头/状态码与降级的完整测试用例t/plugin/ext-plugin/extra-info.t包含ext-plugin-post-resp路由配置的扩展信息Extra Info交互测试t/plugin/ext-plugin/sanity.t插件 schema 校验的冒烟测试docs/zh/latest/external-plugin.mdExternal Plugin 与 Plugin Runner 的概念、部署与常见问题。综上所述ext-plugin-post-resp为 APISIX 提供了一种在响应阶段接入任意语言插件的能力。在规划架构时建议先明确其旁路直连上游、自行回写响应的实现特性妥善规避与 proxy-cache、proxy-mirror、proxy-control 等插件的冲突再结合allow_degradation设计好 Runner 异常时的降级策略即可稳定地将外部生态的复杂响应处理逻辑纳入 APISIX 的请求链路。【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表