Agent 调用外部 API 时,如何处理速率限制(Rate Limiting)
1️⃣ 考察意图
面试官想看你能否设计 Agent 调用外部 API 的限流策略,保证在 API 速率限制下不中断服务。刁钻点在于:Agent 的工具调用模式不可预测(可能突然爆发大量调用),传统限流算法需要调整。答好了能展示你在分布式系统限流和降级方面的经验。
2️⃣ 标准答
速率限制处理从"限流算法、队列缓冲、降级策略、多账号轮换"四个维度设计:
1. 限流算法
- 令牌桶(Token Bucket):以固定速率往桶里加令牌,每次 API 调用消耗一个令牌。桶空时请求被拒绝或排队。允许突发流量(桶满时可以瞬间发送多个请求)。适合大多数 API 限流场景
- 漏桶(Leaky Bucket):请求以固定速率"漏出"执行,超出的请求排队等待。平滑流量但不允许突发。适合需要严格速率控制的场景
- 滑动窗口(Sliding Window):统计过去 N 秒内的请求数,超过阈值拒绝。比固定窗口更精确(避免窗口边界处的突发)。适合有明确 QPS 限制的 API
- 实现方式:用 Redis + Lua 脚本实现分布式限流。Redis 的
INCR+EXPIRE实现固定窗口,ZSET实现滑动窗口
2. 队列缓冲
- 请求队列:超出限流时,请求进入队列等待而非直接拒绝。队列消费者按 API 允许的速率处理请求
- 优先级队列:不同工具调用设不同优先级。例如
transfer_money(高优先级)优先于search(低优先级)。用 Redis Sorted Set 实现 - 超时策略:队列中的请求等待超过 N 秒(如 5s)后自动超时,触发降级。防止请求无限积压
- 背压(Backpressure):队列长度超过阈值(如 100)时,向 Agent 返回"服务繁忙"信号,Agent 可以选择减少调用频率或降级
3. 降级策略
- 缓存降级:API 限流时返回缓存数据(即使已过期),标注"数据可能不是最新的"
- 简化降级:限流时返回简化结果。例如搜索 API 限流时,返回 Top-3 结果而非 Top-10
- 备用 API:主 API 限流时切换到备用 API。例如 Google Search 限流→Bing Search。需要在 Agent 层做 API 切换逻辑
- 模型知识降级:所有外部 API 都限流时,用 LLM 自身知识回答,标注"以下信息可能不是最新的"
4. 多账号轮换
- API Key 池:多个 API Key 轮换使用,每个 Key 有独立的速率限制。例如 10 个 Key × 100 QPS = 总计 1000 QPS
- 轮换策略:(1) 轮询(Round Robin)——简单但可能某个 Key 被频繁限流;(2) 最少使用(Least Used)——选择剩余配额最多的 Key;(3) 随机——避免可预测性
- Key 管理:每个 Key 的用量实时追踪,接近限额时自动切换到其他 Key。用 Redis 记录每个 Key 在当前时间窗口内的使用次数
- 合规风险:多账号轮换可能违反某些 API 的服务条款(如"禁止创建多个账号规避限流")。使用前需确认 API 提供方的政策
3️⃣ 答题模板(30 秒电梯版)
"速率限制四层:限流算法——令牌桶(允许突发)+滑动窗口(精确QPS),Redis+Lua分布式实现。队列缓冲——超限请求排队+优先级队列(转账>搜索)+5s超时降级+背压机制。降级——缓存降级(返回过期数据标注)+简化降级(Top-3替代Top-10)+备用API+模型知识降级。多账号轮换——API Key池轮换,最少使用策略,接近限额自动切换。总结一句:限流不是'拒绝请求'而是'排队+降级+轮换'保证服务不中断。"
4️⃣ 高频追问 & 应对
追问 1:Agent 的工具调用模式不可预测,怎么设置令牌桶的速率?
自适应限流方案:(1) 初始保守——令牌桶速率设为 API 限额的 80%(如限额 100 QPS,设 80 QPS),留 20% 余量应对突发;(2) 动态调整——监控限流触发频率,如果过去 1 小时内未触发限流,逐步提高速率(每次 +5%);如果频繁触发,降低速率(每次 -10%);(3) 多工具共享——多个工具调用同一个 API 时,共享一个令牌桶。用 Agent ID + API 域名作为令牌桶的 key;(4) 用户级限流——不同用户的 Agent 实例有独立的令牌桶,避免一个用户的高频调用影响其他用户
追问 2:队列缓冲会不会导致请求积压?怎么处理?
积压处理三层:(1) 队列长度限制——最大 100 个请求,超过后新请求直接降级而非入队。防止队列无限增长导致内存溢出;(2) 超时丢弃——队列中的请求等待超过 5s 后自动丢弃并触发降级。用户看到的是"降级回答"而非"等待中";(3) 队列监控——队列长度 >50 时告警,提示运维增加 API 配额或扩容备用 API。队列长度 >80 时自动启用"激进降级"——所有非关键工具调用直接返回缓存或模型知识,只保留关键工具的真实调用
追问 3:多账号轮换被 API 提供方封禁了怎么办?
合规替代方案:(1) 企业级 API——向 API 提供方申请企业级配额(如 Google Search API 的企业版支持 10k QPS),而非用多账号规避限流;(2) 自建服务——对于核心功能(如搜索),自建搜索服务(用 Elasticsearch + 爬虫),不依赖第三方 API;(3) 混合策略——低频场景用第三方 API(成本低),高频场景用自建服务(可控性强);(4) 缓存优化——通过提高缓存命中率减少 API 调用。实测缓存命中率从 30% 提升到 60%,API 调用量减少 40%
5️⃣ 避坑 · 常见错误答法
- ❌ "限流就是拒绝请求" → ✅ "拒绝请求是最差的体验。应该排队+降级——排队等待、返回缓存、简化结果、切换备用API。用户不应该感知到限流。"
- ❌ "用 sleep 控制调用速率就行" → ✅ "sleep 是阻塞式的——会阻塞整个 Agent 线程。应该用令牌桶异步控制——请求被拒绝时进入队列而非阻塞,Agent 可以继续处理其他任务。"
- ❌ "多注册几个 API Key 就能解决限流" → ✅ "多账号轮换可能违反服务条款,且增加了 Key 管理复杂度。应该优先优化调用频率(缓存+批量+降级),多账号作为最后手段。"
6️⃣ 简历呼应
- 如果你有高并发项目:从"Agent API 限流系统"切入,描述你实现的令牌桶+队列+降级+多Key轮换体系,给出 QPS 规模和降级触发率
- 如果你只做过微服务限流:用"微服务限流"迁移——令牌桶/漏桶/滑动窗口等算法直接适用,额外需要的是"Agent 特有的不可预测调用模式"和"降级策略"
- 如果你是校招无项目:用 Redis+Lua 实现分布式令牌桶,测试不同限流策略下的 Agent 响应延迟和成功率
- "Rate Limiting Patterns" (Stripe Engineering, 2023)
- "Distributed Rate Limiting with Redis" (Redis Labs, 2024)
- "Backpressure in Reactive Systems" (Reactive Manifesto, 2023)