Plugin

描述

APISIX 插件可以扩展 APISIX 的功能,以满足组织或用户特定的流量管理、可观测性、安全、请求/响应转换、无服务器计算等需求。

APISIX 提供了许多现有的插件,可以定制和编排以满足你的需求。这些插件可以全局启用,以在每个传入请求上触发,也可以局部绑定到其他对象,例如在 RouteServiceConsumerPlugin Config 上。你可以参考 Admin API 了解如何使用该资源。

如果现有的 APISIX 插件不满足需求,你还可以使用 Lua 或其他语言(如 Java、Python、Go 和 Wasm)编写自定义插件。

插件安装

APISIX 附带一个config-default.yaml的默认配置文件和一个 config.yaml 的用户自定义配置文件。这些文件位于conf目录中。如果两个文件中都存在相同的键 (例如plugins),则config.yaml文件中该键的配置值将覆盖config-default.yaml文件中的配置值。

例如:

  1. plugins:
  2. - real-ip # 安装
  3. - ai
  4. - client-control
  5. - proxy-control
  6. - request-id
  7. - zipkin
  8. # - skywalking # 未安装
  9. ...

插件执行生命周期

安装的插件首先会被初始化。然后会检查插件的配置,以确保插件配置遵循定义的JSON Schema

当一个请求通过 APISIX 时,插件的相应方法会在以下一个或多个阶段中执行: rewrite, access, before_proxy, header_filter, body_filter, and log。这些阶段在很大程度上受到OpenResty 指令的影响。

Routes Diagram

插件执行顺序

通常情况下,插件按照以下顺序执行:

  1. 全局规则 插件

    1. rewrite 阶段的插件
    2. access 阶段的插件
  2. 绑定到其他对象的插件

    1. rewrite 阶段的插件
    2. access 阶段的插件

在每个阶段内,你可以在插件的 _meta.priority 字段中可选地定义一个新的优先级数,该优先级数优先于默认插件优先级在执行期间。具有更高优先级数的插件首先执行。

例如,如果你想在请求到达路由时,让 limit-count(优先级 1002)先于 ip-restriction(优先级 3000)运行,可以通过将更高的优先级数传递给 limit-count_meta.priority 字段来实现:

  1. {
  2. ...,
  3. "plugins": {
  4. "limit-count": {
  5. ...,
  6. "_meta": {
  7. "priority": 3010
  8. }
  9. }
  10. }
  11. }

若要将此插件实例的优先级重置为默认值,只需从插件配置中删除_meta.priority字段即可。

插件合并优先顺序

当同一个插件在全局规则中和局部规则(例如路由)中同时配置时,两个插件将顺序执行。

然而,如果相同的插件在多个对象上本地配置,例如在Route, Service, ConsumerPlugin Config 上,每个非全局插件只会执行一次,因为在执行期间,针对特定的优先顺序,这些对象中配置的插件会被合并:

Consumer > Consumer Group > Route > Plugin Config > Service

因此,如果相同的插件在不同的对象中具有不同的配置,则合并期间具有最高优先顺序的插件配置将被使用。

通用配置

通过 _meta 配置项可以将一些通用的配置应用于插件,你可以参考下文使用这些通用配置。通用配置如下:

名称类型描述
disableboolean当设置为 true 时,则禁用该插件。可选值为 truefalse
error_responsestring/object自定义错误响应。
priorityinteger自定义插件优先级。
filterarray根据请求的参数,在运行时控制插件是否执行。此配置由一个或多个 {var, operator, val} 元素组成列表,类似:{{var, operator, val}, {var, operator, val}, …}}。例如 {“arg_version”, “==”, “v2”},表示当前请求参数 versionv2。这里的 var 与 NGINX 内部自身变量命名是保持一致。操作符的使用方法,请参考 lua-resty-expr

禁用指定插件

通过 disable 参数,你可以将某个插件调整为“禁用状态”,即请求不会经过该插件。

  1. {
  2. "proxy-rewrite": {
  3. "_meta": {
  4. "disable": true
  5. }
  6. }
  7. }

自定义错误响应

通过 error_response 配置,可以将任意插件的错误响应配置成一个固定的值,避免因为插件内置的错误响应信息而带来不必要的麻烦。

如下配置表示将 jwt-auth 插件的错误响应自定义为 Missing credential in request

  1. {
  2. "jwt-auth": {
  3. "_meta": {
  4. "error_response": {
  5. "message": "Missing credential in request"
  6. }
  7. }
  8. }
  9. }

自定义插件优先级

所有插件都有默认优先级,但是你仍然可以通过 priority 配置项来自定义插件优先级,从而改变插件执行顺序。

  1. {
  2. "serverless-post-function": {
  3. "_meta": {
  4. "priority": 10000
  5. },
  6. "phase": "rewrite",
  7. "functions" : ["return function(conf, ctx)
  8. ngx.say(\"serverless-post-function\");
  9. end"]
  10. },
  11. "serverless-pre-function": {
  12. "_meta": {
  13. "priority": -2000
  14. },
  15. "phase": "rewrite",
  16. "functions": ["return function(conf, ctx)
  17. ngx.say(\"serverless-pre-function\");
  18. end"]
  19. }
  20. }

serverless-pre-function 的默认优先级是 10000serverless-post-function 的默认优先级是 -2000。默认情况下会先执行 serverless-pre-function 插件,再执行 serverless-post-function 插件。

上面的配置则将 serverless-pre-function 插件的优先级设置为 -2000serverless-post-function 插件的优先级设置为 10000,因此 serverless-post-function 插件会优先执行。

Plugin - 图2注意
  • 自定义插件优先级只会影响插件实例绑定的主体,不会影响该插件的所有实例。比如上面的插件配置属于路由 A,路由 B 上的插件 serverless-post-functionserverless-post-function 插件执行顺序不会受到影响,会使用默认优先级。
  • 自定义插件优先级不适用于 Consumer 上配置的插件的 rewrite 阶段。路由上配置的插件的 rewrite 阶段将会优先运行,然后才会运行 Consumer 上除 auth 类插件之外的其他插件的 rewrite 阶段。

动态控制插件执行状态

默认情况下,在路由中指定的插件都会被执行。但是你可以通过 filter 配置项为插件添加一个过滤器,通过过滤器的执行结果控制插件是否执行。

  1. 如下配置表示,只有当请求查询参数中 version 值为 v2 时,proxy-rewrite 插件才会执行。

    1. {
    2. "proxy-rewrite": {
    3. "_meta": {
    4. "filter": [
    5. ["arg_version", "==", "v2"]
    6. ]
    7. },
    8. "uri": "/anything"
    9. }
    10. }
  2. 使用下述配置创建一条完整的路由。

    1. {
    2. "uri": "/get",
    3. "plugins": {
    4. "proxy-rewrite": {
    5. "_meta": {
    6. "filter": [
    7. ["arg_version", "==", "v2"]
    8. ]
    9. },
    10. "uri": "/anything"
    11. }
    12. },
    13. "upstream": {
    14. "type": "roundrobin",
    15. "nodes": {
    16. "httpbin.org:80": 1
    17. }
    18. }
    19. }
  3. 当请求中不带任何参数时,proxy-rewrite 插件不会执行,请求将被转发到上游的 /get

    1. curl -v /dev/null http://127.0.0.1:9080/get -H"host:httpbin.org"
    1. < HTTP/1.1 200 OK
    2. ......
    3. < Server: APISIX/2.15.0
    4. <
    5. {
    6. "args": {},
    7. "headers": {
    8. "Accept": "*/*",
    9. "Host": "httpbin.org",
    10. "User-Agent": "curl/7.79.1",
    11. "X-Amzn-Trace-Id": "Root=1-62eb6eec-46c97e8a5d95141e621e07fe",
    12. "X-Forwarded-Host": "httpbin.org"
    13. },
    14. "origin": "127.0.0.1, 117.152.66.200",
    15. "url": "http://httpbin.org/get"
    16. }
  4. 当请求中携带参数 version=v2 时,proxy-rewrite 插件执行,请求将被转发到上游的 /anything:

    1. curl -v /dev/null http://127.0.0.1:9080/get?version=v2 -H"host:httpbin.org"
    1. < HTTP/1.1 200 OK
    2. ......
    3. < Server: APISIX/2.15.0
    4. <
    5. {
    6. "args": {
    7. "version": "v2"
    8. },
    9. "data": "",
    10. "files": {},
    11. "form": {},
    12. "headers": {
    13. "Accept": "*/*",
    14. "Host": "httpbin.org",
    15. "User-Agent": "curl/7.79.1",
    16. "X-Amzn-Trace-Id": "Root=1-62eb6f02-24a613b57b6587a076ef18b4",
    17. "X-Forwarded-Host": "httpbin.org"
    18. },
    19. "json": null,
    20. "method": "GET",
    21. "origin": "127.0.0.1, 117.152.66.200",
    22. "url": "http://httpbin.org/anything?version=v2"
    23. }

热加载

APISIX 的插件是热加载的,不管你是新增、删除还是修改插件,都不需要重启服务。

只需要通过 Admin API 发送一个 HTTP 请求即可:

  1. curl http://127.0.0.1:9180/apisix/admin/plugins/reload -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT
Plugin - 图3注意

如果你已经在路由规则里配置了某个插件(比如在 Route 的 plugins 字段里面添加了它),然后在配置文件中禁用了该插件,在执行路由规则时则会跳过该插件。

Standalone 模式下的热加载

关于 Stand Alone 模式下的热加载的信息,请参考 stand alone 模式