Apache APISIX Consumer 对象详解:基于身份识别的细粒度流量治理
【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix
Apache APISIX 的 Consumer(消费者)对象用于标识调用 API 的请求方身份,从而在认证通过后为不同用户执行差异化的插件与上游配置。本文基于官方术语文档,结合源码实现讲解 Consumer 的核心概念、配置字段、识别流程与实战示例,读完即可在真实网关场景中落地基于用户的限流、黑白名单等治理策略。
为什么需要 Consumer
对于 API 网关而言,通常可以通过请求的域名、客户端 IP 等手段区分请求来源,APISIX 可以据此借助 Plugin 过滤请求,并转发到指定的 Upstream。
但这在有些场景下并不够用。网关更关心的是:到底是谁在调用这个 API。只有知道了调用方是谁,才能为不同的调用方配置不同的规则,例如"同一个接口,A 客户限流 100 次/分钟,B 客户限流 1000 次/分钟"。
上图直观表达了这一诉求:多个请求方访问 APISIX 时,网关需要先回答"who are you?"(你是谁),再决定后续如何对待这个请求。这正是 APISIX 中Consumer构造要解决的问题。
在 APISIX 的配置优先级中,Consumer 拥有最高优先级:Consumer > Route > Plugin Config > Service。也就是说,当同一个路由同时被多个消费者命中时,挂在 Consumer 上的插件配置会优先生效。
Consumer 的配置字段
Consumer 对象的核心字段定义如下(与 schema_def.lua 中的 consumer schema 一一对应):
| 字段 | 必填 | 描述 |
|---|---|---|
username | 是 | Consumer 的名称,也是其唯一标识,格式要求匹配^[a-zA-Z0-9_]+$(字母、数字、下划线) |
plugins | 否 | Consumer 级别的插件配置,具体插件配置方式参考 Plugin |
group_id | 否 | 关联的 Consumer Group 的 id(用于批量管理插件配置) |
labels | 否 | 标签,用于资源分类与检索 |
desc | 否 | 描述信息 |
从源码看,schema_def.lua 的_M.consumer规定username为必填(required = {"username"}),且不允许出现未定义的额外字段(additionalProperties = false)。
值得注意的是,username同时就是 Consumer 的id。在 apisix/consumer.lua 的 filter 函数 中有明确处理:
-- We expect the id is the same as username. Fix up it here if it isn't. consumer.value.id = consumer.value.username即无论请求中如何填写 id,最终都会以username作为 Consumer 的唯一标识,后续认证插件拿到的consumer_name也来自这里(见 plugin_consumer 中的注释)。
Consumer 的识别流程
APISIX 中识别一个 Consumer 的过程分为三步:
- 认证(Authentication):由认证类插件完成,例如 key-auth、JWT;
- 获取 Consumer id:认证通过后得到 Consumer 的
id(即username),作为该 Consumer 的唯一标识; - 执行绑定配置:执行挂载在该 Consumer 上的 Plugin、Upstream 等配置。
底层实现上,apisix/consumer.lua 的plugin_consumer()会在初始化时遍历 etcd 中/consumers下的所有 Consumer,筛选出其中配置了type == "auth"插件的项,将插件配置提取为auth_conf并缓存。认证插件(如 key-auth)通过_M.consumers_kv(plugin_name, consumer_conf, key_attr)(consumer.lua L116-L121)以"认证键"为索引建立 KV 缓存,实现 O(1) 的消费者查找。
认证通过后,认证插件调用_M.attach_consumer(ctx, consumer, conf)(consumer.lua L84-L89)将 Consumer 挂到请求上下文上:
function _M.attach_consumer(ctx, consumer, conf) ctx.consumer = consumer ctx.consumer_name = consumer.consumer_name ctx.consumer_group_id = consumer.group_id ctx.consumer_ver = conf.conf_version end此后,consumer-restriction、limit-count等插件即可通过ctx.consumer_name感知到当前请求的消费者身份,从而执行差异化策略。
Consumer 最适合的场景是:多个不同的消费者访问同一个 API,需要根据消费者身份执行不同的插件与上游配置。这类能力必须与用户认证体系配合使用。
APISIX 中可与 Consumer 配合的认证插件包括:basic-auth、hmac-auth、jwt-auth、key-auth、ldap-auth、wolf-rbac。
更深入的概念可以结合 key-auth 认证插件文档理解;Consumer 对象的 Admin API 资源说明参见 Admin API Consumer。
实战示例:为特定 Consumer 启用插件
下面通过完整示例演示如何为指定 Consumer 启用插件。示例将使用key-auth做身份认证,并用limit-count对该消费者做限流。
首先,从config.yaml中取出管理密钥并保存为环境变量(Admin API 默认监听127.0.0.1:9180,数据面默认监听127.0.0.1:9080):
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')1. 创建 Consumer
创建一个名为jack的 Consumer,指定认证插件key-auth,并启用限流插件limit-count(60 秒窗口内最多 2 次请求,超出返回 503):
curl http://127.0.0.1:9180/apisix/admin/consumers \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "username": "jack", "plugins": { "key-auth": { "key": "auth-one" }, "limit-count": { "count": 2, "time_window": 60, "rejected_code": 503, "key": "remote_addr" } } }'说明:Admin API 对 Consumer 只支持
PUT与DELETE,不支持POST与PATCH(见 apisix/admin/consumers.lua 的 unsupported_methods)。PUT时 URI 中的 username 必须与请求体中的username一致,否则会返回wrong username错误(见 check_conf)。同时,Admin API 强制校验:Consumer 的
plugins中必须包含至少一个认证类(type 为 auth)插件,否则返回require one auth plugin(consumers.lua L40-L50)。这从管理面保证了"Consumer 必须能被认证识别"这一设计初衷。
2. 创建路由并开启插件
创建路由/hello,在路由上启用key-auth(网关先完成认证),并将请求转发到上游127.0.0.1:1980:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "plugins": { "key-auth": {} }, "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" }, "uri": "/hello" }'3. 验证限流效果
发送测试请求,携带jack的认证密钥auth-one:
curl http://127.0.0.1:9080/hello -H 'apikey: auth-one' -I- 前两次请求正常返回,未达到限流阈值;
- 第三次请求返回
503,请求被限流拦截:
HTTP/1.1 503 Service Temporarily Unavailable ...这正是 Consumer 级插件配置的典型效果:限流规则只作用于jack这一个消费者,不影响其他消费者访问同一路由。
进阶:用 consumer-restriction 做访问控制
除了限流,还可以用 consumer-restriction 插件按消费者身份做访问控制。下面把jack加入黑名单,禁止其访问该 API。
1. 在路由上配置黑名单
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "plugins": { "key-auth": {}, "consumer-restriction": { "blacklist": [ "jack" ] } }, "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" }, "uri": "/hello" }'2. 验证拦截效果
再次使用jack的密钥发起请求:
curl http://127.0.0.1:9080/hello -H 'apikey: auth-one' -I反复测试均返回403,jack已被禁止访问该 API:
HTTP/1.1 403 ...补充说明与源码路径
- 配置优先级:Consumer > Route > Plugin Config > Service,意味着消费者维度的插件配置会覆盖路由维度的同名配置,这也是实现"同一接口不同客户不同策略"的基础。
- Consumer 与 Consumer Group:当多个 Consumer 需要共享同一组插件配置时,可以通过
group_id关联 Consumer Group 批量管理,避免逐个重复配置。 - 数据加载:Consumer 配置在
init_worker阶段通过core.config.new("/consumers", cfg)(consumer.lua L139-L155)从 etcd(或独立部署下的配置文件)加载,并在 etcd 配置变更时自动热更新,无需重启网关。 - 相关资源:
- Consumer 核心实现:apisix/consumer.lua
- Consumer Admin API 实现:apisix/admin/consumers.lua
- Consumer Schema 定义:apisix/schema_def.lua
- 认证插件参考:key-auth、jwt-auth
- 相关测试:t/admin/consumers.t、t/node/consumer-plugin.t
总而言之,Consumer 是 APISIX 将"请求"与"人"关联起来的关键抽象。配合认证插件,它让网关能够在同一路由上针对不同调用方执行限流、黑白名单、灰度等精细化策略,是构建多租户、多客户 API 治理体系的基石能力。
【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考