APISIX Golang插件

Apache APISIX 是 Apache 软件基金会下的顶级项目。它是一个具有动态、实时、高性能等特点的云原生 API 网关。它构建于 NGINX + ngx_lua 的技术基础之上,充分利用了 LuaJIT 所提供的强大性能。


APISIX 主要分为两个部分:

  1. APISIX 核心:包括 Lua 插件、多语言插件运行时(Plugin Runner)、Wasm 插件运行时等;

  2. 功能丰富的各种内置插件:包括可观测性、安全、流量控制等。

APISIX 在其核心中,提供了路由匹配、负载均衡、服务发现、API 管理等重要功能,以及配置管理等基础性模块。除此之外,APISIX 插件运行时也包含其中,提供原生 Lua 插件的运行框架和多语言插件的运行框架,以及实验性的 Wasm 插件运行时等。APISIX 多语言插件运行时提供多种开发语言的支持,比如 Golang、Java、Python、JS 等。

APISIX 目前也内置了各类插件,覆盖了 API 网关的各种领域,如认证鉴权、安全、可观测性、流量管理、多协议接入等。当前 APISIX 内置的插件使用原生 Lua 实现


此次使用golang开发一个ApiSix的插件。


一、git clone apisix golang 运行环境SDK

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

插件目录位于:cmd/go-runner/plugins 文件夹中,直接在此文件夹中创建插件文件即可;

plugins目录中有示例插件代码,可以全部删除;

二、开发流程

1、定义一个结构体,包含 plugin.DefaultPlugin,并实现plugin.Plugin接口,如:

// 定义一个包含DefaultPlugin的结构体
type MyResponseRewrite struct {
	plugin.DefaultPlugin
}

// 实现Plugin接口的Name
func (m *MyResponseRewrite) Name() string {
	return "my-response-rewrite"
}

// 实现Plugin接口的ParseConf
func (m *MyResponseRewrite) ParseConf(in []byte) (interface{}, error) {
	conf := MyRewriteResponseConf{}
	err := json.Unmarshal(in, &conf)
	return conf, err
}

2、注册插件

通过init方法注册插件

func init() {
	err := plugin.RegisterPlugin(&MyResponseRewrite{})
	if err != nil {
		log.Fatalf("failed to register plugin my-response-rewrite: %s", err)
	}
}


3、根据业务需求重写 plugin.DefaultPlugin的方法;DefaultPlugin 只有两个方法:

// 请求时处理,Request是请求参数,只读;ResponseWriter是响应参数,读写, conf 是自定义的插件配置
func (*DefaultPlugin) RequestFilter(conf interface{},w http.ResponseWriter,r pkgHTTP.Request) {}

// 响应时处理,响应时只有Response和conf
func (*DefaultPlugin) ResponseFilter(conf interface{},w pkgHTTP.Response)                    {}

4、make build 的方式生成插件

在根目录执行make build生成插件;

windows如未安装 make 工具链,可下载 minGW 安装,minGW安装后加入到环境变量,minGW安装的 make 工具被命名为:mingw-make.exe ,可复制后修改为make.exe ;

注:最好是在liunx环境中编译,windows系统可以 wls 中进行编译;


5、把生成的 go-runner 插件保存到apisix运行的服务器,且 apisix对插件必须具有访问执行权限;

比如:把go-runner 复制到 apisix服务器的 /usr/local/apisix-go-plugin-runner/ 目录

如果是docker运行的apisix可以把插件目录映射到宿主机;


6、配置apisix_conf/config.yaml文件

设置环境变量

SET APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock
SET APISIX_CONF_EXPIRE_TIME=3600

添加ext-plugin

ext-plugin:
  # path_for_test: /tmp/runner.sock ## 没有设置APISIX_LISTEN_ADDRESS环境变量的情况下,生产环境官方建议设置APISIX_LISTEN_ADDRESS变量
  cmd: ["/path/to/apisix-go-plugin-runner/go-runner", "run"] ## /path/to/apisix-go-plugin-runner/go-runner 为插件的路径

重启APISIX,检查插件是否随APISIX启动:

ps -elf  | grep apisix
4 S root         1     0  0  80   0 - 90038 sigsus 08:38 ?        00:00:00 nginx: master process /usr/local/openresty/bin/openresty -p /usr/local/apisix -g daemon off;
0 S root       107    57  0  80   0 - 78161 futex_ 08:38 ?        00:00:00 /usr/local/apisix-go-plugin-runner/go-runner run
0 S root       129   115  0  80   0 -  2275 pipe_w 08:50 pts/0    00:00:00 grep apisix

## 如果有显示插件的进程即已启动,如果没有可以手动启动插件


7、配置插件

插件注册及启动后,只是在后台运行,要使用插件还需要在APISIX路由中配置插件(在服务中配置插件无效,不知道是不是我配置的问题)

配置go-runner插件需要使用到 ext-plugin-* 插件中的一个指定外部插件的运行时

ext-plugin-pre-req

ext-plugin-pre-req 插件用于在执行内置 Lua 插件之前和在 Plugin Runner 内运行特定的 External Plugin。


ext-plugin-post-req

ext-plugin-post-req 插件的功能与 ext-plugin-pre-req 插件的不同之处在于:ext-plugin-post-req 插件是在内置 Lua 插件执行之后且在请求到达上游之前工作。


ext-plugin-post-resp

ext-plugin-post-resp 插件用于在执行内置 Lua 插件之前和在 Plugin Runner 内运行特定的 External Plugin。

ext-plugin-post-resp 插件将在请求获取到上游的响应之后执行。

启用本插件之后,APISIX 将使用 lua-resty-http 库向上游发起请求,这会导致:


如配置在ext-plugin-post-resp 运行:

{
  "uri": "/api/*",
  "name": "api",
  "methods": [
    "GET",
    "POST"
  ],
  "plugins": {
    "ext-plugin-post-resp": {
      "_meta": {
        "disable": false
      },
      "conf": [
        {
          "name": "my-response-rewrite",
          "value": "{\"tag\":\"hello my-rewrite-response\"}"
        }
      ]
    }
  }
}

注意ext-plugin-*插件默认不在APISIX Dashboard上显示,需要到dashboard_conf/conf.yaml配置文件中添加,后更新schema.json;

注:更新 schema.json,在apisix服务器上(如果是部署在docker,需要在容器中执行)执行:

curl 127.0.0.1:9092/v1/schema > schema.json

## 9092端口是 control_api 的默认端口,有时这个端口会被修改,可能查看apisix_conf/conf.yaml 中的control设置的是什么端口

## docker 把 schema.json 导出到宿主机:
docker cp 容器名称:schema.json schema.json

## 把schema.json导入到apisix-dashboard 的conf目录:/usr/local/apisix-dashboard/conf
docker cp scheam.json 容器名称:/usr/local/apisix-dashboard/conf


Related Posts

APISIX Golang插件

Apache APISIX 是 Apache 软件基金会下的顶级项目。它是一个具有动态、实时、高性能等特点的云原生 API 网关。它构建于 NGINX + ngx_lua 的技术基础之上,充分利用了 LuaJIT 所提供的强大性能。

Read More