给Agent调用做限流熔断保护

📅 2026/6/26 2:08:15
给Agent调用做限流熔断保护
先把结论甩出来:Agent 调大模型/工具,一定要在客户端这侧加限流(令牌桶) 熔断(连续失败就短路) 退避重试,三件套缺一不可。我上个月就是没加,被自己写的循环把账号打到限流封了 20 分钟,顺带烧了我自己一笔不算少的 token。下面是我踩完坑后现在固定用的那套写法。我是怎么把自己打爆的故事很蠢。我做了个自动跑财报摘要的小东西,let 它对一个 PDF 列表挨个调模型抽要点。某次列表里有 312 个文件,我图省事写了个for循环,await都没好好排队,直接并发怼上去。结果:前 40 个还行,第 41 个开始狂返 429我没做退避,失败了立刻重试,等于火上浇油大概一分钟后整个 key 被限流,凉了最离谱的是,有十几个请求其实是同一个超大 PDF,模型那边超时 30 秒才报错,我这边没设超时,干等。那一晚上我盯着日志,心态有点崩。三件套,逐个拆1限流:令牌桶,控住你自己别等服务端 429,你自己先把流量压住。令牌桶最好用——平时匀速发,允许小突发,桶空了就排队。import asyncio, time class TokenBucket: def __init__(self, rate, burst): self.rate, self.cap rate, burst self.tokens, self.ts burst, time.monotonic() async def take(self): while True: now time.monotonic() self.tokens min(self.cap, self.tokens (now-self.ts)*self.rate) self.ts now if self.tokens 1: self.tokens - 1 return await asyncio.sleep((1-self.tokens)/self.rate) # 缺多少补多少调模型前先await bucket.take()。我现在默认 rate5/s、burst10,够用了。2熔断:连续失败就别再戳了服务端已经在喘了,你还一个劲发,纯属添乱。熔断器三态:closed:正常放行open:失败计数超阈值,直接短路,根本不发请求,立刻报错half-open:冷却一段时间后放一个试探请求,成了就恢复class Breaker: def __init__(self, fails5, cool15): self.fails, self.cool fails, cool self.cnt, self.opened_at 0, 0 def allow(self): if self.cnt self.fails: return True if time.monotonic() - self.opened_at self.cool: return True # half-open:放一个试探 return False # open:直接拒,省得打爆 def ok(self): self.cnt 0 def bad(self): self.cnt 1 self.opened_at time.monotonic()熔断和限流不是一回事:限流管我发多快,熔断管对面挂了我还发不发。两个一起上。3退避重试:抖动别忘重试要指数退避,而且必须加随机抖动,不然一堆请求同一秒醒来,又是一波雪崩。async def call_with_retry(fn, tries4): for i in range(tries): try: return await fn() except RateLimited: wait min(2**i, 8) random.random() # 抖动 await asyncio.sleep(wait) raise一张表理清楚机制解决啥触发点我的默认值令牌桶限流我发太快发请求前5/s,突发10熔断对面已经挂了连续失败5次/冷却15s退避重试偶发抖动单次失败4次,带抖动超时请求卡死每个调用20s超时那行最容易漏。务必给每一次调用单独设超时,别让一个卡住的请求拖垮整条链路。后来我换了个思路省心写到第三版我有点烦——限流参数、模型并发上限、不同模型的 QPS 配额,全得我自己摸。后来给团队里非技术的同事搭东西,我干脆用了个零代码就能配智能体的平台:拖几个节点、挂上现成模型、把知识库接进去,一个能用的小助手就出来了,调用配额这些它后台帮你兜着,我不用再手搓令牌桶。说实话第一版搭出来挺干的,回答短得像敷衍,我对着提示词调了小半天才像样;响应也比我本地直连慢个一两拍。但胜在那位同事自己就能改流程,不用每次来找我。我这边的限流熔断代码,就只留给真正高并发的批处理任务用了。熔断这东西吧,平时根本想不起来,出事那一晚你会无比庆幸当初写了。你们的 Agent 有没有被自己打爆过?评论区聊聊你踩的是哪种——并发没控、还是重试没退避?(模型/API 我走的讯飞星辰 MaaS,现成调,没自己部署,省了一摊算力的事)