
Apache APISIX openwhisk 插件将无服务器函数无缝接入 API 网关【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix导读openwhisk是 Apache APISIX 内置的动态上游插件它把开源的分布式无服务器平台 Apache OpenWhisk 直接作为 API 网关的上游集成进来客户端请求到达 APISIX 后插件会代表客户端向 OpenWhisk 的 API Host 发起新的请求并执行指定 action再把函数返回结果转发回客户端。读完本文你将掌握该插件的全部配置属性、如何搭建 OpenWhisk 独立测试环境、如何在路由上启用/删除插件以及从源码层面理解插件内部请求终止—转发—响应解析的完整链路。插件概述与工作原理openwhisk插件位于 apisix/plugins/openwhisk.lua并已列入 apisix/cli/config.lua 中plugins默认启用列表与aws-lambda、azure-functions、openfunction等函数计算类插件并列安装后无需额外配置即可直接使用。启用该插件后插件在access阶段终止对已配置 URI 的请求它不再把请求转发给普通 upstream而是代表客户端向 OpenWhisk API Host 端点发起一个新请求执行指定的 action然后将响应信息原样返回客户端。其核心行为可以从源码中看到插件优先级为-1901数值越小越先执行version 0.1access(conf, ctx)是唯一的核心回调内部完成请求构造、发送与响应解析。属性Attributes详解插件属性表如下其中标注源码补充的字段是属性表中未列出、但源码 apisix/plugins/openwhisk.lua 实际支持的配置项名称类型必选项默认值有效值描述api_hoststring是--OpenWhisk API Host 地址例如https://localhost:3233。ssl_verifyboolean否true-设置为true时执行 SSL 证书验证。service_tokenstring是--OpenWhisk service token格式为xxx:xxx用于 API 调用时的身份认证。namespacestring是--OpenWhisk namespace例如guest。actionstring是--OpenWhisk action例如hello。resultboolean否true-设置为true时获取 action 元数据执行函数并获得响应结果。timeoutinteger否3000源码默认值[1, 60000]msOpenWhisk action 和 HTTP 调用超时时间毫秒。keepaliveboolean否true-设置为true时保持连接的活动状态以便重复使用。keepalive_timeoutinteger否60000ms[1000, ...]ms连接空闲时保持活动状态的时间毫秒。keepalive_poolinteger否5[1, ...]连接断开之前可接收的最大请求数。packagestring否--源码补充OpenWhisk package 名用于调用打包packagedaction例如pkg。encrypt_fields----源码补充service_token被声明为加密字段启用数据加密后存储于 etcd 中的凭证为密文。timeout 与 keepalive 的约束细节关于timeout官方文档与源码给出了一致的安全建议timeout同时规定了 OpenWhisk action 的最大执行时间和 APISIX 中 HTTP 客户端的请求超时时间因为 OpenWhisk action 调用可能需要较长时间来拉取容器镜像和启动容器如果该值设置太小可能导致大量请求失败OpenWhisk 支持 1ms 到 60000ms 的超时范围建议至少设置为 1000ms。在源码中timeout的 schema 定义为minimum 1, maximum 60000, default 3000keepalive_timeout的最小值为 1000mskeepalive_pool的最小值为 1。此外namespace、package、action三个字段都受maxLength 256与正则[\w][\w .-]*[\w.-]的约束名称中不允许出现斜杠等特殊字符因为 endpoint 拼接依赖这些字段构建 URL。字段命名与字符串校验从 t/plugin/openwhisk.t 的测试用例可以看出 schema 校验的行为缺少必填字段property api_host is requiredTEST 2类型错误property api_host validation failed: wrong type: expected string, got numberTEST 3。可见四个必填字段api_host、service_token、namespace、action缺一不可且api_host必须是字符串。启用插件第一步搭建 Apache OpenWhisk 测试环境在使用插件之前需要先有一个可用的 OpenWhisk 实例。以下命令以 standalone 模式运行 OpenWhisk请确保环境中已安装 Dockerdocker run --rm -d \ -h openwhisk --name openwhisk \ -p 3233:3233 -p 3232:3232 \ -v /var/run/docker.sock:/var/run/docker.sock \ openwhisk/standalone:nightly docker exec openwhisk waitready说明-p 3233:3233暴露 OpenWhisk API 端口HTTP-p 3232:3232暴露内部控制器端口挂载/var/run/docker.sock是为了让 OpenWhisk 能够按需拉取运行时镜像并启动函数容器。waitready命令会阻塞等待服务就绪。第二步安装 openwhisk-cliwsk下载 openwhisk-cli 仓库中发布的适用于 Linux 系统的可执行二进制文件wsk将其加入PATH即可使用。第三步在 OpenWhisk 中注册函数使用wsk配置 API Host 与认证信息并创建一个测试 actionwsk property set --apihost http://localhost:3233 --auth ${service_token} wsk action update test (echo function main(){return {ready:true}}) --kind nodejs:14其中${service_token}是你在 OpenWhisk 中获取的xxx:xxx格式凭证第二行命令通过进程替换将一个返回{ready:true}的 Node.js 函数注册为名为test的 action。测试套件中使用的实际凭证形如23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP见 t/plugin/openwhisk.t。第四步创建路由并绑定插件通过 Admin API 在指定路由上启用插件。先从conf/config.yaml中读取admin_key并存入环境变量admin_key$(yq .deployment.admin.admin_key[0].key conf/config.yaml | sed s///g)然后创建路由curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { uri: /hello, plugins: { openwhisk: { api_host: http://localhost:3233, service_token: ${service_token}, namespace: guest, action: test } } }配置要点uri: /hello声明该插件拦截的路径api_host必须与wsk property set中的--apihost一致http://localhost:3233service_token与上一步--auth相同namespace使用默认的guestOpenWhisk standalone 模式默认存在action指向刚注册的test函数。注意此示例中没有配置upstream节点因为该插件的请求目标完全由api_host决定。测试用例 t/plugin/openwhisk.t 中也是以空节点nodes: {}搭配 roundrobin 方式创建的。第五步测试请求curl -i http://127.0.0.1:9080/hello正常返回结果{ ready: true }即 APISIX 代替客户端调用了 OpenWhisk 中的testaction并把函数返回值透传给了客户端。源码级原理请求构造与响应解析要深入理解插件行为关键在于 apisix/plugins/openwhisk.lua 中_M.access的实现。上游请求的构造插件向 OpenWhisk 发起的请求参数如下local params { method POST, body core.request.get_body(), query { blocking true, result tostring(conf.result), timeout conf.timeout }, headers { [Authorization] Basic .. ngx_encode_base64(conf.service_token), [Content-Type] application/json, }, keepalive conf.keepalive, ssl_verify conf.ssl_verify }要点解读总是使用 POST 方法并把客户端原始请求体原样转发core.request.get_body()认证方式service_token经 Base64 编码后放入Authorization: Basic ...头这与 OpenWhisk 的 Basic Auth 约定一致blockingtrue以阻塞方式调用 action等待函数执行完返回结果而非异步提交任务result 与 timeout作为 query 参数透传给 OpenWhisk控制是否返回执行结果及最大执行时间连接复用当keepalive true时额外设置keepalive_timeout与keepalive_pool复用与 OpenWhisk 之间的 HTTP 连接。目标端点的拼接local package conf.package and conf.package .. / or local endpoint conf.api_host .. /api/v1/namespaces/ .. conf.namespace .. /actions/ .. package .. conf.action最终请求的 URL 形如http://localhost:3233/api/v1/namespaces/guest/actions/test。如果配置了package如pkg则 URL 为/namespaces/guest/actions/pkg/test这正是测试用例 TEST 14/15packaged action验证的行为。连接与超时设置local httpc http.new() httpc:set_timeout(conf.timeout)使用lua-resty-http创建 HTTP 客户端并把conf.timeout同时设置为 socket 超时时间与文档timeout 同时约束 action 执行与 HTTP 调用的描述一致。失败的兜底处理if not res then core.log.error(failed to process openwhisk action, err: , err) return 503 end当 OpenWhisk 不可达或连接失败时插件记录 error 日志并直接返回503。测试用例 TEST 13 将api_host指向不存在的127.0.0.1:1979断言响应码为503且日志中出现failed to process openwhisk action, err:。响应解析支持三种 OpenWhisk 返回风格local result, err core.json.decode(res.body) if result.headers ~ nil then core.response.set_header(result.headers) end local code result.statusCode or res.status local body result.body or res.body return code, bodyOpenWhisk action 支持两种返回方式只返回响应体或显式设置状态码与响应头。插件将 OpenWhisk 的 JSON 响应解码后若 JSON 中含headers则通过core.response.set_header透传为 APISIX 响应头状态码优先取 JSON 中的statusCode否则使用 OpenWhisk 原始 HTTP 状态码响应体优先取 JSON 中的body否则使用原始响应体。这一点被 t/plugin/openwhisk.t 的多个用例覆盖自定义状态码TEST 17 中断言返回407action 通过 statusCode 返回自定义响应头TEST 19 中断言响应头test: headeraction 通过 headers 返回自定义响应体TEST 21 中断言返回{test:body}action 通过 body 返回。请求体格式的校验行为测试用例 TEST 6/7/9 还揭示了插件对请求体的处理当客户端以application/x-www-form-urlencoded发送非 JSON 格式请求体时OpenWhisk 返回400及The request content was malformed错误而使用 JSON 请求体{name: world}时action 可以正确读取参数并返回{hello:world}。这说明插件会原样透传请求体与 Content-Type格式校验由 OpenWhisk 侧完成。关于 service_token 的加密存储值得留意的是源码在 schema 中声明了encrypt_fields {service_token}。这意味着当 APISIX 配置中启用数据加密data_encryption.enable_encrypt_fields且配置中心为 etcd 时service_token会以 AES 加密后的密文形式存储运行时由 apisix/plugin.lua 中的加解密逻辑自动解密后使用。测试用例 TEST 5 正是从 etcd 读取路由配置断言plugins[openwhisk].service_token已经是不可读的密文字符串。删除插件需要移除该插件时通过 Admin API 重新 PUT 一条不带openwhisk插件配置的路由即可。APISIX 会自动重新加载相关配置无需重启服务curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { methods: [GET], uri: /hello, upstream: { type: roundrobin, nodes: { 127.0.0.1:1980: 1 } } }该操作的本质是将原路由的plugins配置替换为普通 upstream 配置此处指向127.0.0.1:1980的 roundrobin 节点openwhisk插件随之失效路由回归常规代理模式。实战经验小结超时务必留足OpenWhisk 冷启动拉镜像、启容器可能耗时数秒timeout建议不低于 1000ms过小会导致大规模 503api_host 要可达插件对连接失败直接返回 503配置前先用curl验证api_host/api/v1/namespaces/guest可访问打包 action 需 package 字段OpenWhisk 的 package 内 action 必须显式配置package参数否则 URL 拼接不到正确端点凭证安全service_token支持加密字段存储生产环境建议开启 APISIX 的数据加密能力函数返回风格灵活action 可只返回 body也可携带statusCode、headers控制响应头与状态码插件均能正确透传便于在网关侧保留完整的函数语义。深入阅读路径插件完整实现见 apisix/plugins/openwhisk.luaschema 校验工具见 apisix/core/utils.lua21 个覆盖 schema、加密、转发与响应透传的回归测试见 t/plugin/openwhisk.t英文版文档见 docs/en/latest/plugins/openwhisk.md。【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考