Agent限流区分用户组,免费版限制工具调用次数

Agent 接入越来越多的用户后,如果不按用户组区分限流,免费用户很容易把共享额度耗尽,付费用户又可能被误伤。
本文要解决的就是在 Agent 网关或业务层,按用户组设置不同的工具调用次数限制,并针对免费版单独收紧额度,让限流策略精确到组而不是全局一刀切。
全文基于常见网关中间件和业务代码给出可直接复用的配置方法,零基础也能照着操作。

先想清楚限流维度:按用户组还是按单个用户

配置之前,先明确你的限流对象。
常见的做法有两种:

  • 按用户组限流:同一组内所有用户共享一个额度池。适合免费版、体验版、企业版这种套餐维度控制。
  • 按单个用户限流:每个用户独立计数,互不影响。适合内部系统或需要精细审计的场景。

如果你的目标是“免费版限制工具调用次数”,通常采用 用户组限流
实现时,需要两个数据:用户所属组(免费组、付费组)和该组对应的次数阈值。
用户组可以从用户表中读取,也可以从 JWT 或会话缓存里直接拿。
建议在网关层统一解析,避免每个业务服务都重复写判断。

配置步骤:从用户组识别到限流规则生效

下面以常见的网关 + Redis 计数方案为例,演示完整配置过程。
假设你有两个组:free(免费版)和 premium(付费版),免费版每分钟最多调用 10 次工具,付费版每分钟 60 次。

1. 在用户表或认证信息中标记用户组

如果用户表还没分组字段,先加一列:

alter table users add column group_name varchar(20) default 'free';

已有用户可以手动更新,例如把内部账号划到付费组:

update users set group_name = 'premium' where email = 'admin@example.com';

实际生产环境建议让登录接口在生成 token 时把 group_name 写进 JWT claims,这样后续限流中间件不需要再查数据库。

2. 编写限流中间件,按组取阈值

使用 Node.js + Express 的示意代码如下:

const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis').RedisStore;
const redisClient = require('./redis');

const groupLimits = {
  free: { windowMs: 60 * 1000, max: 10 },
  premium: { windowMs: 60 * 1000, max: 60 }
};

function agentLimiter(req, res, next) {
  const group = req.user?.group_name || 'free';
  const limit = groupLimits[group] || groupLimits.free;

  const limiter = rateLimit({
    store: new RedisStore({
      sendCommand: (...args) => redisClient.sendCommand(args)
    }),
    windowMs: limit.windowMs,
    max: limit.max,
    keyGenerator: (req) => `${req.user.id}:${group}:tools`, // 按用户+组组合计数
    handler: (req, res) => {
      res.status(429).json({ error: '工具调用次数超限,请升级套餐或稍后再试' });
    }
  });

  return limiter(req, res, next);
}

app.use('/api/agent/tools', agentLimiter);

上面的配置里,keyGenerator 用了 用户 ID + 组名 + 动作类型 的组合,
这样每个用户在所属组内独立计数,
同时组名变化后计数键也会变化,
避免把免费用户升级后旧额度残留成问题。

3. 免费版的工具调用入口单独挂更严格的限制

如果你的免费版只开放一小部分工具,最好把免费版能调用的工具接口单独列出来,然后对这段路由使用更严格的限流。
例如:

app.use('/api/agent/tools/free', rateLimit({
  windowMs: 60 * 1000,
  max: 5,
  message: '免费版每分钟仅支持 5 次工具调用,请升级后解锁更多次数'
}));

注意这里不要再叠加一个全局的 agentLimiter,否则会出现两次计数,用户还没到真实阈值就被拦截。
通常做法是:在网关层先路由到具体工具模块,再应用对应的限流规则。

验证限流是否生效:制造超限请求

配置完成后,用 curl 模拟不同的用户组进行验证。

先造一个免费版用户请求:

curl -H "Authorization: Bearer " \
  http://localhost:3000/api/agent/tools/translate

连续请求超过 10 次后,应该看到 429 响应,并返回你自定义的 JSON 错误信息。

再换付费用户 token 测试,确认 60 次以内不拦截。

还可以直接查 Redis 里的计数键:

redis-cli keys '*tools*'
redis-cli get ":free:tools"

如果 key 存在且数值在递增,说明限流计数正在正常工作。

避坑要点:这几个问题最容易踩

用户组不存在时默认按免费组处理
很多系统忘了处理未知组,导致认证信息异常的请求直接绕过限流。
建议中间件里对所有无法识别组名的请求,一律使用最低限额。

注意限流键是否包含用户 ID
如果只按组名计数,那么一个免费用户狂刷会消耗整个免费组的额度,其他用户跟着遭殃。
如果只想控制单个用户,key 里就不要放组名;
如果想组内共享额度,key 只能放组名。
按你的业务需求二选一,别混用。

免费版限制工具调用次数后,要给出友好的返回提示
不要只抛一个 429 状态码,用户不知道发生了什么。
返回体里最好写明剩余配额、重置时间或升级路径,这样运营压力会小很多。

升级用户组后,旧计数可能还残留
因为 key 里带了组名,用户从 free 变成 premium 后,free 的 key 不再被使用,计数自然失效,这种情况是安全的。
但如果你的 key 只有用户 ID,升级后必须手动清掉旧 key。

判断限流策略是否合理:看两个指标

配置完成后,别急着上线,先观察一段时间。
重点看两个指标:

  • 免费组命中限流的请求占比:如果超过 30%,说明免费额度设置得太低,或者恶意刷量太多,需要调整阈值或加验证码。
  • 付费组是否出现误拦截:如果付费用户也频繁收到 429,检查是不是 key 设计共享了额度,或者时间窗口设置不合理。

建议在日志里把限流命中的用户 ID、组名、接口路径和 IP 都记录下来,方便后续分析。
日志格式可以这样:

{"time":"2025-03-01 12:00:01","user_id":10086,"group":"free","path":"/api/agent/tools/translate","action":"limited"}

以上是按用户组区分限流、免费版限制工具调用次数的基础配置方法。
实际部署时,如果并发量高,可以再引入令牌桶或滑动窗口算法,但对于大多数中小项目,Redis 固定窗口已经足够。
先把组维度拆清、阈值设好、提示写明白,限流就不会成为产品体验的拦路虎。

如果你正在调整 Agent 的免费版策略,建议先用一个测试用户组跑完整流程,确认计数、拦截、提示都符合预期后再全量放开,这样比直接改生产规则更稳妥。

分享到:
上一篇
微调模型量化,INT4/INT8压缩降低显存占用
下一篇
RAG混合多向量库,不同业务使用不同向量引擎
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意