如何使用 Go 开发 Apache APISIX 插件
关 注 微 信 公 众 号 《 云 原 生 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]
参考资料
参考地址: https://apisix.apache.org/blog/2021/08/19/go-makes-Apache-APISIX-better/
- 云原生下一步的发展方向是什么?
- 用更云原生的方式做诊断|大规模 K8s 集群诊断利器深度解析
- 多个维度分析k8s多集群管理工具,到底哪个才真正适合你
- 使用 Kube-capacity CLI 查看 Kubernetes 资源请求、限制和利用率
- 使用 Go 在 Kubernetes 中构建自己的准入控制器
- 云原生数仓如何破解大规模集群的关联查询性能问题?
- 云原生趋势下的迁移与灾备思考
- 2022 年不容错过的六大云原生趋势!
- 使用 Prometheus 监控 Golang 应用程序
- 云原生时代下的机遇与挑战 DevOps如何破局
- 如何在云原生格局中理解Kubernetes合规性和安全框架
- 设计云原生应用程序的15条基本原则
- 使用 Operator SDK 为 Pod 标签编写Controller
- Kubernetes Visitor 模式
- 为什么云原生是第二次云革命
- 构建云原生安全的六个重要能力
- 扩展云原生策略的步骤有哪些?
- 七个值得关注的开源云原生工具
- K8S - 创建一个 kube-scheduler 插件
- 如何诊断 Kubernetes 应用程序中的 OOMKilled 错误