如何使用 Go 开发 Apache APISIX 插件

语言: CN / TW / HK

C T O

   

   

 

Go Rust Python Istio containerd CoreDNS Envoy etcd Fluentd Harbor Helm Jaeger Kubernetes Open Policy Agent Prometheus Rook TiKV TUF Vitess Argo Buildpacks CloudEvents CNI Contour Cortex CRI-O Falco Flux gRPC KubeEdge Linkerd NATS Notary OpenTracing Operator Framework SPIFFE SPIRE     Thanos

如何使用 Go 开发 Apache APISIX 插件

Apache APISIX 允许用户通过插件来扩展功能。鉴权、限流、请求重写等功能都是通过插件实现的。…

本文详细解释了如何使用 Go 开发 Apache APISIX 插件。通过拥抱 Go 生态系统, Go 使 Apache APISIX 变得更好!

安装 Go Runner

使用 Go Runner 作为库, apisix-go-plugin-runnercmd/go-runner 中的官方示例展示了如何使用 Go Runner SDK Go Runner SDK 未来还将支持通过 Go Plugin 机制加载预编译插件。

https://github.com/apache/apisix-go-plugin-runner

开发 Go Runner

使用 Go Runner SDK 进行开发 官方示例的目录结构如下图所示。

$ tree cmd/go-runner
cmd/go-runner
├── main.go
├── main_test.go
├── plugins
│   ├── say.go
│   └── say_test.go
└── version.go

main.go 是入口点,这里是最关键的部分。

cfg := runner.RunnerConfig{}
...
runner.Run(cfg)

RunnerConfig 可用于控制日志级别和日志输出位置。 runner.Run 将使应用程序监听目标位置,接收请求并执行注册的插件。应用程序将保持此状态,直到退出。打开 plugins/say.go .

func init() {
  err := plugin.RegisterPlugin(&Say{})
  if err != nil {
    log.Fatalf("failed to register plugin say: %s", err)
  }
}

由于 main.go 导入了插件包,

import (
  ...
  _ "github.com/apache/apisix-go-plugin-runner/cmd/go-runner/plugins"
  ...
)

这在 Say 执行 plugin.RegisterPlugin 之前注册 runner.Run。 Say 需要实现以下方法。该 Name 方法返回插件名称。

func (p *Say) Name() string {
  return "say"
}

ParseConf 将在插件配置更改时调用,解析配置并返回插件特定的配置上下文。

func (p *Say) ParseConf(in []byte) (interface{}, error) {
  conf := SayConf{}
  err := json.Unmarshal(in, &conf)
  return conf, err
}

插件的上下文如下:

type SayConf struct {
  Body string `json:"body"`
}

Filter 将在每个 Say 配置了插件的请求上执行。

func (p *Say) Filter(conf interface{}, w http.ResponseWriter, r pkgHTTP.Request) {
  body := conf.(SayConf).Body
  if len(body) == 0 {
    return
  }

  w.Header().Add("X-Resp-A6-Runner", "Go")
  _, err := w.Write([]byte(body))
  if err != nil {
    log.Errorf("failed to write: %s", err)
  }
}

可以看到 Filter 把配置里面 body 的值作为 response body 。如果直接在插件中做出响应,则会中断请求。详情请参考 Go Runner SDK API 文档。

https://pkg.go.dev/github.com/apache/apisix-go-plugin-runner

构建应用程序后( make build 在示例中),需要在运行时设置两个环境变量。

  • 1、APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock

  • 2、APISIX_CONF_EXPIRE_TIME=3600 像这样:

APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock APISIX_CONF_EXPIRE_TIME=3600 ./go-runner run

应用程序将 /tmp/runner.sock 在运行时进行监听。

设置 Apache APISIX(开发)

第一步是安装 Apache APISIX ,它需要与 Go Runner 位于同一实例中。

上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 负责运行用不同语言编写的外部插件。 apisix-go-plugin-runner 就是这样一个支持 Go 语言的运行器。

Apache APISIX 中配置插件运行器时, Apache APISIX 会将插件运行器视为自己的子进程,与 Apache APISIX 进程属于同一用户,当我们重新启动或重新加载 Apache APISIX 时,插件运行器也会重新启动.

如果为给定路由配置了 ext-plugin-* 插件,则命中该路由的请求将触发 Apache APISIX 通过 unix 套接字对插件运行器进行 RPC 调用。通话分为两个阶段。

ext-plugin-pre-req :在实现大部分 Apache APISIX 内置插件( Lua 语言插件)之前

  • ext-plugin-post-req :执行 Apache APISIX 内置插件( Lua 语言插件)后

请根据需要配置插件运行器的执行时间。插件运行器处理 RPC 调用,在其中创建模拟请求,然后运行用其他语言编写的插件并将结果返回给 Apache APISIX 。这些插件的执行顺序在 ext-plugin-* 插件配置条目中定义。与其他插件一样,它们可以即时启用和重新定义。为了展示如何开发 Go 插件,我们首先设置 Apache APISIX 进入开发模式。将以下配置添加到 config.yaml

ext-plugin:
  path_for_test: /tmp/runner.sock

这个配置意味着在命中路由规则后, Apache APISIX 会向 /tmp/runner.sock 发起 RPC 请求。接下来,设置路由规则。

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
  "uri": "/get",
  "plugins": {
    "ext-plugin-pre-req": {
      "conf": [
        {"name":"say", "value":"{\"body\":\"hello\"}"}
      ]
    }
  },
  "upstream": {
        "type": "roundrobin",
        "nodes": {
            "127.0.0.1:1980": 1
        }
    }
}
'

注意插件名配置在 name ,插件配置( JSON 序列化后)放在 value . 如果您在开发期间看到 refresh cache and try againApache APISIX 上的 key not found 警告和 Runner 上的警告,这是由于配置缓存不一致造成的。由于 Runner 在开发状态下不受 Apache APISIX 管理,内部状态可能不一致。别担心 ,Apache APISIX 会重试。然后我们请求: curl 127.0.0.1:9080/get

$ curl http://127.0.0.1:9080/get
HTTP/1.1 200 OK
Date: Mon, 26 Jul 2021 11:16:11 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Resp-A6-Runner: Go
Server: APISIX/2.7

hello

可以看到接口返回 hello ,并没有访问任何上游。

设置 Apache APISIX(运行)

下面是一个 go-runner 的例子,只需在 ext-plugin 中配置运行命令行即可运行。

Apache APISIX 将插件运行器视为自己的子进程并管理其整个生命周期。

注意:此时不要配置 path_for_test。Apache APISIX 会自动为运行程序分配一个 unix 套接字地址,以便在它启动时进行监听。不需要手动设置。

概括

Go Plugin Runner 仍处于早期开发阶段,我们将继续改进其功能。欢迎您参与 apisix-go-plugin-runner 的开发,让我们一起架起 Apache APISIX Go 之间的桥梁!

https://github.com/apache/apisix-go-plugin-runner

相关文章

如何用 Java 编写 Apache APISIX 插件

https://medium.com/@ApacheAPISIX/how-to-write-an-apache-apisix-plugin-in-java-3fb7b75444fa

关于 Apache APISIX

Apache APISIX 是一个动态、实时、高性能的 API 网关。 Apache APISIX 提供了丰富的流量管理功能,例如负载均衡、动态上游、金丝雀发布、熔断、身份验证、可观察性等。您可以使用 Apache APISIX 来处理传统的南北向流量,以及服务之间的东西向流量。它也可以用作 k8s 入口控制器。

Github:https ://github.com/apache/apisix 网站:https ://apisix.apache.org

参考地址 [1]

参考资料

[1]

参考地址: https://apisix.apache.org/blog/2021/08/19/go-makes-Apache-APISIX-better/