ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Higress ai-quota 插件实战:基于 Redis 的按 Consumer AI Token 配额管理与管控接口

Higress ai-quota 插件实战:基于 Redis 的按 Consumer AI Token 配额管理与管控接口 Higress ai-quota 插件实战基于 Redis 的按 Consumer AI Token 配额管理与管控接口【免费下载链接】higress AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higress本文围绕 Higress 官方 WASM 插件ai-quota展开完整讲解其配置参数、部署示例以及配额校验—Token 扣减—查询/刷新/增减配额的完整工作流。读完本文你将掌握如何为每个 AI 调用方consumer分配固定 Token 配额、在流式响应结束时自动扣减配额并内置一套基于管理 consumer 身份的配额管控 HTTP 接口同时了解插件在 proxy-wasm 各阶段的底层实现逻辑。功能定位与运行属性ai-quota插件为特定 consumer 分配固定的 quota配额按配额策略对 AI 请求进行限流同时提供配额管理能力包括查询 quota、刷新 quota、增减 quota。其典型使用模式是在网关路由上为不同调用方如不同租户、不同 API Key 持有者预先在 Redis 中写入一个 Token 数值每次调用大模型完成接口时插件校验该 consumer 是否还有剩余配额无配额则直接拒绝大模型响应结束流式或非流式后插件从响应中解析本次请求消耗的 input/output Token并从 Redis 配额中扣减管理员可通过管理接口在线查询、刷新、增减某个 consumer 的配额无需重启网关或手工操作 Redis。根据文档说明ai-quota需要配合认证插件如key-auth、jwt-auth获取认证身份的 consumer 名称配合ai-statistics插件获取 AI Token 统计信息。插件运行属性属性值插件执行阶段默认阶段UNSPECIFIED_PHASE插件执行优先级750文档标称默认优先级在 plugin.yaml 的部署示例中ai-quota 的priority设置为280介于 key-auth300与 ai-statistics250之间。从源码结构看这一顺序保证了认证插件先于配额插件执行、先写入 consumer 标识配额插件再读取该标识完成校验。配置参数详解插件顶层配置项如下与 README.md 一致默认值已结合 main.go 中parseConfig的实际解析逻辑核对名称数据类型填写要求默认值描述redis_key_prefixstring选填chat_quota:quota Redis key 前缀admin_consumerstring必填-管理 quota 管理身份的 consumer 名称admin_pathstring选填/quota管理 quota 请求 path 前缀enable_path_suffixes[]string选填[/v1/chat/completions, /v1/messages]启用配额校验的请求路径后缀仅用于 completion 请求不影响管理接口路径redisobject必填-Redis 相关配置parseConfig中的关键校验逻辑见 main.go#L80-L151未配置admin_consumer时直接返回错误missing admin_consumer in config插件启动失败enable_path_suffixes必须是数组且不能为空元素中的空白串会被过滤空数组会触发enable_path_suffixes must not be emptyadmin_path缺省回退为/quotaredis_key_prefix缺省回退为chat_quota:redis.service_name不能为空且会基于它创建FQDNCluster类型的 Redis 客户端。redis子对象各字段配置项类型必填默认值说明service_namestring必填-Redis 服务名称带服务类型的完整 FQDN 名称例如my-redis.dns、redis.my-ns.svc.cluster.localservice_portint否服务类型为固定地址static service即名称以.static结尾时默认 80其他为 6379Redis 服务端口usernamestring否-Redis 用户名passwordstring否-Redis 密码timeoutint否1000Redis 连接超时时间单位毫秒databaseint否0使用的数据库 id例如配置为 1对应SELECT 1源码中对service_port的默认值处理见 main.go#L123-L131仅当服务名以.static结尾时才取 80这与文档描述一致。完整配置示例以下示例来自文档表示按请求头中的 API Key 识别不同 consumer 并进行区别限流redis_key_prefix: chat_quota: admin_consumer: consumer3 admin_path: /quota redis: service_name: redis-service.default.svc.cluster.local service_port: 6379 timeout: 2000结合仓库中 plugin.yaml 的完整部署形态该插件通常与key-auth、ai-statistics一起以WasmPluginCR 声明式下发。key-auth 侧声明了三个 consumer# 摘自 plugins/wasm-go/extensions/ai-quota/plugin.yaml defaultConfig: consumers: - credential: Bearer credential1 name: consumer1 - credential: Bearer credential2 name: consumer2 - credential: Bearer credential3 name: consumer3 global_auth: true keys: - authorization in_header: true priority: 300ai-quota 侧则配置admin_consumer: consumer3即持有credential3的请求被视为配额管理员。matchRules 通过ingress: [qwen]将配额策略绑定到具体的 Ingress 路由上。请求路径的模式识别completion / admin / none插件在请求头阶段会调用getOperationMode判定当前请求属于哪种模式见 main.go#L289-L306模式判定条件行为admin/refresh请求路径以/v1/chat/completionsadmin_path/refresh结尾刷新配额admin/delta请求路径以/v1/chat/completionsadmin_path/delta结尾增减配额admin/query请求路径以/v1/chat/completionsadmin_path结尾查询配额completion请求路径以enable_path_suffixes中任一后缀结尾执行配额校验与扣减none以上均不匹配放行不做配额处理需要注意两个源码级细节管理接口路径是固定拼接的fullAdminPath : /v1/chat/completions adminPath也就是说无论路由前缀是什么管理接口始终挂在/v1/chat/completions之后默认即/v1/chat/completions/quota系列路径。单元测试TestGetOperationMode中专门验证了/v1/messages/quota不会被识别为管理接口messages admin path not supported用例而自定义后缀如/llm/invoke可以被识别为 completion 路径completion 判定与 admin 判定互不影响enable_path_suffixes只约束配额校验的完成接口路径不改变管理接口的匹配逻辑。该表驱动测试完整位于 main_test.go#L304-L394。配额校验与 Token 扣减流程请求头阶段读取身份并校验配额onHttpRequestHeaders见 main.go#L153-L209的处理链路读取请求头x-mse-consumer由 key-auth 等认证插件在认证成功后写入头不存在返回401状态详情ai-quota.no_key正文 Request denied by ai quota check. No Key Authentication information found.头存在但为空返回403状态详情ai-quota.unauthorized判定模式后none模式直接ActionContinue放行admin模式交由后续 body 阶段处理refresh/delta 会先缓冲请求体completion模式跳过请求体读取发起 RedisGET {redis_key_prefix}{consumer}以下任一情况判定为拒绝Redis 调用出错、key 不存在null、配额值小于等于 0拒绝时返回403状态详情ai-quota.noquota正文 Request denied by ai quota check, No quota left。配额检查期间返回HeaderStopAllIterationAndWatermark即挂起请求流水线直到 Redis 回调返回结果这是 proxy-wasm 中典型的异步外部调用暂停/恢复模式。单元测试TestOnHttpRequestHeaders的 chat completion mode 用例验证了该行为模拟 Redis 返回配额 1000 后流恢复为ActionContinue见 main_test.go#L111-L133。响应体阶段解析 Token 并扣减配额在流式响应体处理函数onHttpStreamingResponseBody见 main.go#L239-L277中插件逐段解析 SSE 流通过 wasm-go 通用包tokenusage.GetTokenUsage提取usage字段中的 input/output token 数仅当endOfStream为 true 且 input/output token 均已解析成功时计算totalToken inputToken outputToken并执行 RedisDECRBY {redis_key_prefix}{consumer} totalToken中间分片数据原样透传不改动响应内容。TestOnHttpStreamingResponseBody用例模拟了流结束后的扣减调用验证了 Redis 扣减回调被正确触发见 main_test.go#L238-L302。配额管理接口实战管理接口同样要求请求先通过认证并携带x-mse-consumer且该 consumer 必须等于admin_consumer否则返回403ai-quota.unauthorizedUnauthorized admin consumer.。以下命令以插件生效于example.com/v1/chat/completions路由、admin_consumer为consumer3对应Bearer credential3为前提。刷新 quota将指定 consumer 的配额直接重置为新值curl https://example.com/v1/chat/completions/quota/refresh \ -H Authorization: Bearer credential3 \ -d consumerconsumer1quota10000执行后 Redis 中 keychat_quota:consumer1的值被刷新为 10000成功时插件返回refresh quota successful。refreshQuota实现位于 main.go#L308-L341请求体按application/x-www-form-urlencoded解析consumer不能为空、quota必须是整数否则返回 403。查询 quota查询指定 consumer 的剩余配额curl https://example.com/v1/chat/completions/quota?consumerconsumer1 \ -H Authorization: Bearer credential3返回 JSON{quota: 10000, consumer: consumer1}若 key 不存在则返回quota: 0。queryQuota在请求头阶段即可处理无需请求体Redis 出错时返回503ai-quota.error。对应实现见 main.go#L343-L385测试用例TestOnHttpRequestHeaders的 admin query mode 断言了返回值{consumer:consumer1,quota:500}。增减 quota对指定 consumer 的配额做增量调整curl https://example.com/v1/chat/completions/quota/delta \ -H Authorization: Bearer credential3 \ -d consumerconsumer1value100Redis 中 keychat_quota:consumer1的值增加 100value支持负数传负值则减去对应值。deltaQuota见 main.go#L387-L435根据正负号分别走 RedisINCRBY/DECRBY成功时返回delta quota successful。错误响应一览结合 util/http.go 的SendResponse与各处理函数插件可能返回的响应如下状态码状态详情status detail触发场景401ai-quota.no_key请求头缺少x-mse-consumer未通过认证插件403ai-quota.unauthorizedconsumer 为空管理接口调用者不是admin_consumer参数校验失败consumer 为空、quota/value 非整数403ai-quota.noquotacompletion 请求无剩余配额key 不存在、出错或值 ≤ 0503ai-quota.errorRedis 调用失败200ai-quota.refreshquota/ai-quota.queryquota/ai-quota.deltaquota管理操作成功这些带语义的 status detail 便于在网关访问日志中直接定位限流/管理请求的处理结果。配置解析的测试覆盖插件配置解析由TestParseConfig覆盖见 main_test.go#L69-L106基础配置解析后各字段符合预期AdminConsumer、RedisKeyPrefix、AdminPath、EnablePathSuffixes缺少admin_consumer时插件启动状态为OnPluginStartStatusFailed即网关侧会拒绝加载该配置属于启动期强校验未配置enable_path_suffixes时回退到默认值[/v1/chat/completions, /v1/messages]兼容 OpenAI 与 Anthropic 两种主流的 completion 路径。落地建议小结先认证后限流务必确保 key-auth / jwt-auth 等认证插件在 ai-quota 之前执行部署示例中通过 priority 300 280 体现否则所有请求都会以 401ai-quota.no_key被拒预置配额consumer 的配额 key如chat_quota:consumer1需提前写入 Redis未写入的 consumer 会被判定为无配额而拒绝这一点在源码中由IsNull()判断直接体现管理面收敛admin_consumer的凭据只分发给运营/管理侧账号管理接口与普通 completion 接口共用同一路由路径前缀区分/quota、/quota/refresh、/quota/delta无需额外暴露管理端口注意管理路径的固定形态管理接口始终基于/v1/chat/completions拼接若网关实际路由前缀不同需要确保客户端 URL 与该形态一致否则请求会落入none模式直接放行而不做配额处理。核心源码均位于 plugins/wasm-go/extensions/ai-quota 目录入口与全部业务逻辑在 main.go本地响应构造工具在 util/http.go行为验证在 main_test.go可直接作为二次开发与排障的参考起点。【免费下载链接】higress AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higress创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表