Apache APISIX openwhisk 插件:将无服务器函数无缝接入 API 网关
2026/9/15 20:50:35 网站建设 项目流程

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-lambdaazure-functionsopenfunction等函数计算类插件并列),安装后无需额外配置即可直接使用。

启用该插件后,插件在access阶段"终止"对已配置 URI 的请求:它不再把请求转发给普通 upstream,而是代表客户端向 OpenWhisk API Host 端点发起一个新请求,执行指定的 action,然后将响应信息原样返回客户端。其核心行为可以从源码中看到:

  • 插件优先级为-1901(数值越小越先执行),version = 0.1
  • access(conf, ctx)是唯一的核心回调,内部完成请求构造、发送与响应解析。

属性(Attributes)详解

插件属性表如下,其中标注"源码补充"的字段是属性表中未列出、但源码 apisix/plugins/openwhisk.lua 实际支持的配置项:

名称类型必选项默认值有效值描述
api_hoststring--OpenWhisk API Host 地址,例如https://localhost:3233
ssl_verifybooleantrue-设置为true时执行 SSL 证书验证。
service_tokenstring--OpenWhisk service token,格式为xxx:xxx,用于 API 调用时的身份认证。
namespacestring--OpenWhisk namespace,例如guest
actionstring--OpenWhisk action,例如hello
resultbooleantrue-设置为true时,获取 action 元数据(执行函数并获得响应结果)。
timeoutinteger3000(源码默认值)[1, 60000]msOpenWhisk action 和 HTTP 调用超时时间(毫秒)。
keepalivebooleantrue-设置为true时保持连接的活动状态以便重复使用。
keepalive_timeoutinteger60000ms[1000, ...]ms连接空闲时保持活动状态的时间(毫秒)。
keepalive_poolinteger5[1, ...]连接断开之前可接收的最大请求数。
packagestring--(源码补充)OpenWhisk package 名,用于调用打包(packaged)action,例如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的最小值为 1000ms,keepalive_pool的最小值为 1。此外,namespacepackageaction三个字段都受maxLength = 256与正则[\w][\w@ .-]*[\w@.-]+的约束,名称中不允许出现斜杠等特殊字符(因为 endpoint 拼接依赖这些字段构建 URL)。

字段命名与字符串校验

从 t/plugin/openwhisk.t 的测试用例可以看出 schema 校验的行为:

  • 缺少必填字段property "api_host" is required(TEST 2);
  • 类型错误property "api_host" validation failed: wrong type: expected string, got number(TEST 3)。

可见四个必填字段api_hostservice_tokennamespaceaction缺一不可,且api_host必须是字符串。

启用插件

第一步:搭建 Apache OpenWhisk 测试环境

在使用插件之前,需要先有一个可用的 OpenWhisk 实例。以下命令以 standalone 模式运行 OpenWhisk(请确保环境中已安装 Docker):

docker 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-cli(wsk)

下载 openwhisk-cli 仓库中发布的适用于 Linux 系统的可执行二进制文件wsk,将其加入PATH即可使用。

第三步:在 OpenWhisk 中注册函数

使用wsk配置 API Host 与认证信息,并创建一个测试 action:

wsk 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:3233);
  • service_token与上一步--auth相同;
  • namespace使用默认的guest(OpenWhisk 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 约定一致;
  • blocking=true:以阻塞方式调用 action,等待函数执行完返回结果(而非异步提交任务);
  • result 与 timeout:作为 query 参数透传给 OpenWhisk,控制是否返回执行结果及最大执行时间;
  • 连接复用:当keepalive = true时,额外设置keepalive_timeoutkeepalive_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/15(packaged 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, body

OpenWhisk action 支持两种返回方式:只返回响应体,或显式设置状态码与响应头。插件将 OpenWhisk 的 JSON 响应解码后:

  • 若 JSON 中含headers,则通过core.response.set_header透传为 APISIX 响应头;
  • 状态码优先取 JSON 中的statusCode,否则使用 OpenWhisk 原始 HTTP 状态码;
  • 响应体优先取 JSON 中的body,否则使用原始响应体。

这一点被 t/plugin/openwhisk.t 的多个用例覆盖:

  • 自定义状态码:TEST 17 中断言返回407(action 通过 statusCode 返回);
  • 自定义响应头:TEST 19 中断言响应头test: header(action 通过 headers 返回);
  • 自定义响应体:TEST 21 中断言返回{"test":"body"}(action 通过 body 返回)。

请求体格式的校验行为

测试用例 TEST 6/7/9 还揭示了插件对请求体的处理:当客户端以application/x-www-form-urlencoded发送非 JSON 格式请求体时,OpenWhisk 返回400The 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插件随之失效,路由回归常规代理模式。

实战经验小结

  1. 超时务必留足:OpenWhisk 冷启动(拉镜像、启容器)可能耗时数秒,timeout建议不低于 1000ms,过小会导致大规模 503;
  2. api_host 要可达:插件对连接失败直接返回 503,配置前先用curl验证api_host/api/v1/namespaces/guest可访问;
  3. 打包 action 需 package 字段:OpenWhisk 的 package 内 action 必须显式配置package参数,否则 URL 拼接不到正确端点;
  4. 凭证安全service_token支持加密字段存储,生产环境建议开启 APISIX 的数据加密能力;
  5. 函数返回风格灵活:action 可只返回 body,也可携带statusCodeheaders控制响应头与状态码,插件均能正确透传,便于在网关侧保留完整的函数语义。

深入阅读路径:插件完整实现见 apisix/plugins/openwhisk.lua,schema 校验工具见 apisix/core/utils.lua,21 个覆盖 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询