除了 APISIX 官方内置的插件之外,我们也可以根据自己的需求去自定义插件,要自定义插件需要使用到 APISIX 提供的 Runner,目前已经支持 Java、Go 和 Python 语言的 Runner,这个 Runner 相当于是 APISIX 和自定义插件之间的桥梁,比如 apache-apisix-python-runner 这个项目通过 Python Runner 可以把 Python 直接应用到 APISIX 的插件开发中,整体架构如下所示:

其中的 Plugin Runner 就是各语言的插件运行器,当配置 Plugin Runner 后,APISIX 会启动一个子进程运行 Plugin Runner,该子进程与 APISIX 进程属于同一个用户,当我们重启或重新加载 APISIX 时,Plugin Runner 也将被重启。

如果你为一个给定的路由配置了 ext-plugin-* 插件,请求命中该路由时将触发 APISIX 通过 Unix Socket 向 Plugin Runner 发起 RPC 调用。调用分为两个阶段:

  • ext-plugin-pre-req :在执行 APISIX 内置插件之前

  • ext-plugin-post-req :在执行 APISIX 内置插件之后

接下来我们就以 Python 为例来说明如何自定义插件,首先获取 apache-apisix-python-runner 项目:

➜ git clone https://github.com/apache/apisix-python-plugin-runner.git
➜ cd apisix-python-plugin-runner
➜ git checkout 0.1.0  # 切换刀0.1.0版本

如果是开发模式,则我们可以直接使用下面的命令启动 Python Runner:

➜ APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock python3 apisix/main.py start

启动后需要在 APISIX 配置文件中新增外部插件配置,如下所示:

➜ vim /path/to/apisix/conf/config.yaml
apisix:admin_key:- name: "admin"key: edd1c9f034335f136f87ad84b625c8f1role: adminext-plugin:path_for_test: /tmp/runner.sock

通过 ext-plugin.path_for_test 指定 Python Runner 的 unix socket 文件路径即可,如果是生产环境则可以通过 ext-plugin.cmd 来指定 Runner 的启动命令即可:

ext-plugin:cmd: [ "python3", "/path/to/apisix-python-plugin-runner/apisix/main.py", "start" ]

我们这里的 APISIX 是运行 Kubernetes 集群中的,所以要在 APISIX 的 Pod 中去执行 Python Runner 的代码,我们自然需要将我们的 Python 代码放到 APISIX 的容器中去,然后安装自定义插件的相关依赖,直接在 APISIX 配置文件中添加上面的配置即可,所以我们这里基于 APISIX 的镜像来重新定制包含插件的镜像,在 apisix-python-plugin-runner 项目根目录下新增如下所示的 Dockerfile 文件:

FROM apache/apisix:2.10.0-alpineADD . /apisix-python-plugin-runnerRUN apk add --update python3 py3-pip && \cd /apisix-python-plugin-runner && \python3 -m pip install --upgrade pip && \python3 -m pip install -r requirements.txt --ignore-installed && \python3 setup.py install --force

基于上面 Dockerfile 构建一个新的镜像,推送到 Docker Hub:

➜ docker build -t cnych/apisix:py3-plugin-2.10.0-alpine .
# 推送到DockerHub
➜ docker push cnych/apisix:py3-plugin-2.10.0-alpine

接下来我们需要使用上面构建的镜像来安装 APISIX,我们这里使用的是 Helm Chart 进行安装的,所以需要通过 Values 文件进行覆盖,如下所示:

# ci/prod.yaml
apisix:enabled: trueimage:repository: cnych/apisixtag: py3-plugin-2.10.0-alpine
......

由于官方的 Helm Chart 没有提供对 ext-plugin 配置的支持,所以需要我们手动修改模板文件 templates/configmap.yaml ,在 apisix 属性同级目录下面新增 ext-plugin 相关配置,如下所示:

{{- if .Values.extPlugins.enabled }}
ext-plugin:{{- if .Values.extPlugins.pathForTest }}path_for_test: {{ .Values.extPlugins.pathForTest }}{{- end }}{{- if .Values.extPlugins.cmds }}cmd:{{- range $cmd := .Values.extPlugins.cmds }}- {{ $cmd }}{{- end }}{{- end }}
{{- end }}nginx_config:user: root  # fix 执行 python runner没权限的问题

然后在定制的 Values 文件中添加如下所示的配置:

# ci/prod.yaml
extPlugins:enabled: truecmds: ["python3", "/apisix-python-plugin-runner/apisix/main.py", "start"]

接着就可以重新部署 APISIX 了:

➜ helm upgrade --install apisix ./apisix -f ./apisix/ci/prod.yaml -n apisix

部署完成后在 APISIX 的 Pod 中可以看到会启动一个 Python Runner 的子进程:

在插件目录 /apisix-python-plugin-runner/apisix/plugins 中的 .py 文件都会被自动加载,上面示例中有两个插件 stop.py 和 rewrite.py ,我们以 stop.py 为例进行说明,该插件代码如下所示:

from apisix.runner.plugin.base import Base
from apisix.runner.http.request import Request
from apisix.runner.http.response import Responseclass Stop(Base):def __init__(self):super(Stop, self).__init__(self.__class__.__name__)def filter(self, request: Request, response: Response):# 可以通过 `self.config` 获取配置信息,如果插件配置为JSON将自动转换为字典结构# print(self.config)# 设置响应 Header 头response.headers["X-Resp-A6-Runner"] = "Python"# 设置响应bodyresponse.body = "Hello, Python Runner of APISIX"# 设置响应状态码response.status_code = 201# 通过调用 `self.stop()` 中断请求流程,此时将立即响应请求给客户端# 如果未显示调用 `self.stop()` 或 显示调用 `self.rewrite()`将继续将请求# 默认为 `self.rewrite()`self.stop()

实现插件首先必须要继承 Base 类,必须实现 filter 函数,插件执行核心业务逻辑就是在 filter 函数中,该函数只包含 Request 和 Response 类对象作为参数, Request 对象参数可以获取请求信息, Response 对象参数可以设置响应信息 , self.config 可以获取插件配置信息,在 filter 函数中调用 self.stop() 时将马上中断请求,响应数据,调用 self.rewrite() 时,将会继续请求。

然后我们在前面的 Nexus 应用中新增一个路由来测试我们上面的 stop 插件,在 ApisixRoute 对象中新增一个路由规则,如下所示:

apiVersion: apisix.apache.org/v2beta2
kind: ApisixRoute
metadata:name: nexusnamespace: default
spec:http:- name: extmatch:hosts:- ops.qikqiak.compaths:- "/extPlugin"plugins:- name: ext-plugin-pre-req  # 启用ext-plugin-pre-req插件enable: trueconfig:conf:- name: "stop"  # 使用 stop 这个自定义插件value: "{\"body\":\"hello\"}"backends:- serviceName: nexusservicePort: 8081

直接创建上面的路由即可,核心配置是启用 ext-plugin-pre-req 插件(前提是在配置文件中已经启用该插件,在 Helm Chart 的 Values 中添加上),然后在 config 下面使用 conf 属性进行配置, conf 为数组格式可以同时设置多个插件,插件配置对象中 name 为插件名称,该名称需要与插件代码文件和对象名称一致, value 为插件配置,可以为 JSON 字符串。

创建后同样在 Dashboard 中也可以看到 APISIX 中的路由配置格式:

接着我们可以来访问 http://ops.qikqiak.com/extPlugin 这个路径来验证我们的自定义插件:

➜ curl -i http://ops.qikqiak.com/extPlugin
HTTP/1.1 201 Created
Date: Thu, 13 Jan 2022 07:04:50 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
accept: */*
user-agent: curl/7.64.1
host: ops.qikqiak.com
X-Resp-A6-Runner: Python
Server: APISIX/2.10.0Hello, Python Runner of APISIX

访问请求结果中有一个 X-Resp-A6-Runner: Python 头信息,返回的 body 数据为 Hello, Python Runner of APISIX ,和我们在插件中的定义是符合的。到这里就完成了使用 Python 进行 APISIX 自定义插件,我们有任何的业务逻辑需要处理直接去定义一个对应的插件即可。

使用 Python 自定义 APISIX 插件相关推荐

  1. arcgis python工具-使用python制作ArcGIS插件(1)工具介绍

    使用python制作ArcGIS插件(1)工具介绍 by 李远祥 ArcGIS从10.0开始支持addin(ArcGIS软件中又叫作加载项)的方式进行插件制作.相对于以往9.x系列,addin的无论是 ...

  2. Android如何自定义Gradle插件

    Android-如何自定义gradle插件 自定义gradle插件可以实现定制自己的构建流程,以达到复用目的: ##1. 自定义插件方式 自定义插件有三种方式 添加脚步 在你的app项目的build. ...

  3. python使用rpa需要什么插件_使用Python制作ArcGIS插件基础篇——工具介绍

    ArcGIS从10.0开始支持addin(ArcGIS软件中又叫作加载项)的方式进行插件制作.相对于以往9.x系列,addin的无论是从使用或者编写都更加方便快捷.通过开发语言,可以制作ArcGIS ...

  4. 使用python制作ArcGIS插件(1)工具介绍

    使用python制作ArcGIS插件(1)工具介绍 by 李远祥 ArcGIS从10.0开始支持addin(ArcGIS软件中又叫作加载项)的方式进行插件制作.相对于以往9.x系列,addin的无论是 ...

  5. pythonarcgis插件_【直播】基于Python开发ArcGIS插件:Python Add-in丨城市数据派

    原标题:[直播]基于Python开发ArcGIS插件:Python Add-in丨城市数据派 Add-in是什么? Add-in(加载项)是一种自定义项(例如工具栏上的工具集合),Add-in可以插入 ...

  6. chrome 窗体高度_Chrome窗口大小自定义调节插件下载_Chrome窗口大小自定义调节插件官方下载-太平洋下载中心...

    Chrome窗口大小自定义调节插件是一款可以设置浏览器窗口大小的Chrome扩展,安装Chrome窗口大小自定义调节插件后可以快速调节chrome的窗口大小,用户可以将窗口调节为320x480.480 ...

  7. python自定义包或模块在Linux服务器导入错误的解决办法

    python自定义包或模块在Linux服务器导入错误的解决办法 在本地机器上跑python代码,自己定义的文件进行导包运行是没有问题,但是放到linux服务器上的时候就会提示 ImportError: ...

  8. Python自定义函数的创建、调用和函数的参数详解

    这篇文章主要介绍了Python自定义函数的创建.调用和函数的参数.变量作用域等常见问题,需要的朋友可以参考下 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性 ...

  9. 【开发环境】Mac 中 IntelliJ IDEA 运行 Python 程序 ( 安装 Python Community Edition 插件 )

    文章目录 一.安装 Python Community Edition 插件 二.创建 Python 工程 一.安装 Python Community Edition 插件 选择 菜单栏 " ...

最新文章

  1. C#.NET 中的类型转换
  2. AutoShape:实时形状感知的单目3D目标检测(ICCV2021)
  3. 哈尔滨金融学院计算机系学生会,哈尔滨金融学院计算机系实习报告(毕业分散实习).doc...
  4. 区别ie8和ie9的方法
  5. 既然是青春,怎么能错过?唯一理由只缺1张免费票!
  6. Oracle代码大全.从入门到熟练
  7. java string rt_如何使jvm加载我的java.lang.String而不是rt.jar中的那个
  8. python启动http服务_Python命令开启http.server服务器
  9. sort,uniq命令
  10. CentOS 网络基础:(1)HostName和DNS
  11. 怎样把网站js文件合并成一个?几种方法可以实现
  12. 谷歌插件无法显示在地址栏右侧
  13. SQLSERVER存储过程实例(上)
  14. python数据类型
  15. paTJPSb桌趴缀岳凳钟涸
  16. misc类设备驱动1——板载蜂鸣器驱动测试
  17. 【Python编程:从入门到实践】第十六章练习题
  18. java桌面应用开发利器JavaFx
  19. 您需要administrator权限才能对此文件进行更改
  20. 带你轻松认识SSL协议中的加密套件

热门文章

  1. Latex局部设置字体大小
  2. 工程伦理--3.2 解决伦理困境的基本理论及方法
  3. 饿了么大数据平台建设
  4. 做为一名大数据新手,应该通过这篇文章了解大数据
  5. 8.10 最大流最小割定理
  6. spring事务@Transactional(readOnly = true)及隔离级别实验
  7. LabVIEW生成.NET的DLL——C#下调用NI数据采集设备功能的一种方法 [原创www.cnblogs.com/helesheng]
  8. 求任意一个正整数的二进制中有多少个比特位为1
  9. 基于欧式聚类的车载路面点云扫描线提取
  10. 自研DSP28335+移相全桥+纯程序实现同步整流