🤔 Introducing APISIX AI Gateway – Built for LLMs and AI workloads. Learn More

serverless

描述

无服务器函数由两个插件组成:serverless-pre-functionserverless-post-function。这些插件支持在执行阶段的开始和结束时执行用户定义的逻辑。

属性

名称类型必选项默认值有效值描述
phasestring”access”[“rewrite”, “access”, “header_filter”, “body_filter”, “log”, “before_proxy”]执行 serverless 函数之前或之后的阶段。
functionsarray[string]按顺序执行的函数列表。

编写函数的提示

serverless 插件中只允许使用 Lua 函数,不允许使用其他 Lua 代码。

例如,匿名函数是合法的:

return function()
    ngx.log(ngx.ERR, 'one')
end

闭包也是合法的:

local count = 1
return function()
    count = count + 1
    ngx.say(count)
end

但不是函数类型的代码就是非法的:

local count = 1
ngx.say(count)

示例

NOTE

你可以这样从 config.yaml 中获取 admin_key 并存入环境变量:

admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')

以下示例演示如何在不同场景中配置 serverless-pre-functionserverless-post-function 插件。

在阶段前后记录信息

以下示例演示如何配置 serverless 插件,在 rewrite 阶段之前和之后执行自定义逻辑,将信息记录到错误日志中。

创建如下路由:

admin-api

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "serverless-pre-route",
    "uri": "/anything",
    "plugins": {
      "serverless-pre-function": {
        "phase": "rewrite",
        "functions" : [
          "return function() ngx.log(ngx.ERR, \"serverless pre function\"); end"
        ]
      },
      "serverless-post-function": {
        "phase": "rewrite",
        "functions" : [
          "return function(conf, ctx) ngx.log(ngx.ERR, \"match uri \", ctx.curr_req_matched and ctx.curr_req_matched._path); end"
        ]
      }
    },
    "upstream": {
      "type": "roundrobin",
      "nodes": {
        "httpbin.org:80": 1
      }
    }
  }'

adc

adc.yaml
services:
  - name: httpbin
    routes:
      - name: serverless-pre-route
        uris:
          - /anything
        plugins:
          serverless-pre-function:
            phase: rewrite
            functions:
              - |
                return function()
                  ngx.log(ngx.ERR, "serverless pre function")
                end
          serverless-post-function:
            phase: rewrite
            functions:
              - |
                return function(conf, ctx)
                  ngx.log(ngx.ERR, "match uri ", ctx.curr_req_matched and ctx.curr_req_matched._path)
                end
    upstream:
      type: roundrobin
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1

同步配置到网关:

adc sync -f adc.yaml

aic

gateway-api

serverless-functions-ic.yaml
apiVersion: v1
kind: Service
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  type: ExternalName
  externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
  namespace: aic
  name: serverless-functions-plugin-config
spec:
  plugins:
    - name: serverless-pre-function
      config:
        phase: rewrite
        functions:
          - |
            return function()
              ngx.log(ngx.ERR, "serverless pre function")
            end
    - name: serverless-post-function
      config:
        phase: rewrite
        functions:
          - |
            return function(conf, ctx)
              ngx.log(ngx.ERR, "match uri ", ctx.curr_req_matched and ctx.curr_req_matched._path)
            end
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  namespace: aic
  name: serverless-pre-route
spec:
  parentRefs:
    - name: apisix
  rules:
    - matches:
        - path:
            type: Exact
            value: /anything
      filters:
        - type: ExtensionRef
          extensionRef:
            group: apisix.apache.org
            kind: PluginConfig
            name: serverless-functions-plugin-config
      backendRefs:
        - name: httpbin-external-domain
          port: 80

apisix-crd

serverless-functions-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  ingressClassName: apisix
  externalNodes:
  - type: Domain
    name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  namespace: aic
  name: serverless-pre-route
spec:
  ingressClassName: apisix
  http:
    - name: serverless-pre-route
      match:
        paths:
          - /anything
      upstreams:
        - name: httpbin-external-domain
      plugins:
        - name: serverless-pre-function
          config:
            phase: rewrite
            functions:
              - |
                return function()
                  ngx.log(ngx.ERR, "serverless pre function")
                end
        - name: serverless-post-function
          config:
            phase: rewrite
            functions:
              - |
                return function(conf, ctx)
                  ngx.log(ngx.ERR, "match uri ", ctx.curr_req_matched and ctx.curr_req_matched._path)
                end

应用配置:

kubectl apply -f serverless-functions-ic.yaml

向路由发送请求:

curl -i "http://127.0.0.1:9080/anything"

你应该会收到 HTTP/1.1 200 OK 响应,并在错误日志中看到以下条目:

2024/05/09 15:07:09 [error] 51#51: *3963 [lua] [string "return function() ngx.log(ngx.ERR, "serverles..."]:1: func(): serverless pre function, client: 172.21.0.1, server: _, request: "GET /anything HTTP/1.1", host: "127.0.0.1:9080"
2024/05/09 15:16:58 [error] 50#50: *9343 [lua] [string "return function(conf, ctx) ngx.log(ngx.ERR, "..."]:1: func(): match uri /anything, client: 172.21.0.1, server: _, request: "GET /anything HTTP/1.1", host: "127.0.0.1:9080"

第一条记录由 pre-function 添加,第二条记录由 post-function 添加。