网易首页 > 网易号 > 正文 申请入驻

900行与3000行:重试风暴事故复盘

0
分享至

```html900行与3000行:重试风暴事故复盘900行与3000行:重试风暴事故复盘

周六早上,周报表格里只有900行,而不是3000行,仪表盘却是一片让人安心的绿色。任务以退出码0结束,死信文件涨到了12MB,三周没人打开过。真正发现这次失败的,是损失已经造成四十分钟后才到的一封配额邮件。

这样的任务你大概也写过:把几千条数据摊开,让模型给每条写两句摘要,写回表格,退出。没人盯着它,因为它已经稳定跑了几个月,唯一接到人身上的信号就是退出码。而当重试循环藏在一个以continue结尾的try块里时,这个信号就开始撒谎了。

下面这条时间线可以对着本地桩服务在二十分钟左右复现出来。重点在于:重试风暴是设计缺陷,不是运气差,而且证明它应该很便宜。

时间线还原

T+0:八个worker在一条3000条的队列上启动,共用一个API key,没有共享的花费计数器。每个worker都以为自己的重试预算就是全局预算。

T+6m:接口开始返回429。退避策略是2 ** attempt,没有抖动也没有上限,于是每个worker睡一样长、一起醒来,把一次限流变成了同步踩踏。

T+22m:每换一条新数据,重试计数就重置,单条数据能烧掉六次尝试,而整轮运行始终没触发自己的任何限制。图上看吞吐很健康,因为图统计的是请求数,不是行数。

T+41m:配额没了。服务方开始返回硬性配额错误,分类器因为它仍是一个HTTP错误而判定可重试,风暴继续全速撞墙。

T+6h:运行以退出码0结束,71%的行缺失。没有任何告警,因为从来没有东西被接到告警上:失败的数据被追加进一个文件,而文件不会叫醒任何人。

三个促成因素,一个根因

第一个因素是分类器。把所有非200响应都当成可重试,和把所有异常都当成临时故障是同一个错误。401、403、404和硬性配额错误都是终态,重试它们只是花钱去确认显而易见的事。

第二个因素是缺失的账本。T+41m时没人能回答唯一重要的问题——这轮运行到目前为止花了多少token——因为这个数字只存在于一个每小时刷新一次的服务商仪表盘里。

第三个因素是沉默的死信。一条失败数据落进文件,没有计数、没有时间、没有告警,这不叫处理,叫藏起来。三者之下的根因是:这个任务没有“运行级预算”的概念,代码和人读不到同一个数。

可落地的修法:账本、上限、软车道

修法是一个可审计的token账本,在你需要它之前就写好。每次尝试一行,按运行ID索引,用量取自响应本身,而不是来自一个你没锁版本的tokenizer估算。

# guard.py — a token ledger you can query at 2amimport random, sqlite3, timeDDL = """CREATE TABLE IF NOT EXISTS attempts (id INTEGER PRIMARY KEY AUTOINCREMENT,run_id TEXT NOT NULL,item_id TEXT NOT NULL,attempt INTEGER NOT NULL,model TEXT NOT NULL,ptok INTEGER NOT NULL DEFAULT 0,ctok INTEGER NOT NULL DEFAULT 0,status TEXT NOT NULL,err TEXT,ts REAL NOT NULLRETRYABLE = {"429", "500", "502", "503", "504"}BUDGET = 200_000 # tokens per run, deliberately below the monthly ceilingMAX_ATTEMPTS = 4class BudgetExhausted(RuntimeError):passdef open_ledger(path="ledger.sqlite"):conn = sqlite3.connect(path, isolation_level=None)conn.execute(DDL)return conndef spent(conn, run_id):q = "SELECT COALESCE(SUM(ptok + ctok), 0) FROM attempts WHERE run_id = ?"return conn.execute(q, (run_id,)).fetchone()[0]def log(conn, run_id, item_id, attempt, model, ptok, ctok, status, err=None):conn.execute("INSERT INTO attempts (run_id,item_id,attempt,model,ptok,ctok,status,err,ts)"" VALUES (?,?,?,?,?,?,?,?,?)",(run_id, item_id, attempt, model, ptok, ctok, status, err, time.time()),)

调用点随后会拒绝启动付不起的工作,并用状态码而不是异常类型来区分“等一等”和“停下来”。

def summarize(client, conn, run_id, item, model="free-lane"):for attempt in range(1, MAX_ATTEMPTS + 1):if spent(conn, run_id) >= BUDGET:log(conn, run_id, item.id, attempt, model, 0, 0, "budget_stop")raise BudgetExhausted(run_id)try:r = client.chat.completions.create(model=model,max_tokens=160,messages=[{"role": "user", "content": item.prompt}],u = r.usagelog(conn, run_id, item.id, attempt, model,u.prompt_tokens, u.completion_tokens, "ok")return r.choices[0].message.contentexcept Exception as e: # narrow this to your SDK's error basecode = str(getattr(e, "status_code", None) or type(e).__name__)log(conn, run_id, item.id, attempt, model, 0, 0, "error", code)if code not in RETRYABLE or attempt == MAX_ATTEMPTS:raisetime.sleep(min(2 ** attempt, 20) + random.uniform(0, 1))

抖动在这里不是锦上添花,它是阻止八个worker变成一个非常昂贵的worker的关键。二十秒的上限则防止长尾把夜间任务拖成早间任务。

一次预检只花一个请求,却能避免最糟的情形:一批任务拿着一个已经死掉的key就开跑。

curl -sS -o /dev/null -w '%{http_code}\n' \"$BASE_URL/models" -H "Authorization: Bearer $KEY"

最后,把车道分开。摘要任务留在你信任质量的模型上,第二条更便宜的车道负责校验:重跑一小批摘要样本、检查JSON外壳还能不能解析、确认行数能和队列对上。免费模型端点真正适合的就是这条车道,因为它的职责是怀疑,不是权威。

MonkeyCode也出现在这个位置,契合度窄到可以如实描述。该项目开源,其材料宣传免费模型额度最高约1000万token,外加一个免费服务器选项,这使它成为那条低风险校验车道的合理去处——容量、限制和时长由项目方设定,依赖它跑任何定时任务之前请先读当前条款。

披露:本文作为MonkeyCode产品推广的一部分撰写。

证明防护有效的测试计划

你没法对着一个健康的端点验证重试防护,所以要造一个故障注入器。标准库四十行就够,而且不花一个token。

# stub.py — a 429 machine, so you can watch the guard behavefrom http.server import BaseHTTPRequestHandler, HTTPServerclass H(BaseHTTPRequestHandler):def do_POST(self):body = b'{"error":{"message":"rate limited","type":"rate_limit_error"}}'self.send_response(429)self.send_header("Content-Type", "application/json")self.send_header("Content-Length", str(len(body)))self.end_headers()self.wfile.write(body)def log_message(self, *args):passHTTPServer(("127.0.0.1", 8787), H).serve_forever()

把BASE_URL指向本地桩,跑一个二十条的夹具。然后断言四件事,而不是用眼睛看日志:尝试总行数不超过二十乘以最大尝试次数;进程以非零码退出而不是0;死信数等于二十;告警触发。再把桩调成让30%的请求失败,断言成功行加死信仍然等于二十——这一条检查就能一行抓住最初那次事故。

真实运行之后,账本可以直接回答审计问题:按状态分组,数行数,加token。

SELECT status, COUNT(*) AS n, SUM(ptok + ctok) AS tokensFROM attempts WHERE run_id = ? GROUP BY status;
局限,以及谁该跳过

账本是按运行、按文件的,扩到多台机器就需要真正的数据库和行锁,而不是共享卷上的SQLite。流式响应在不同服务商那里上报用量的方式可能不同,这意味着ptok/ctok两列会和账单有偏差,应当当作上限估算而非会计数字。免费额度会不打招呼地变化,所以永远别让校验车道成为你和数据静默缺失之间的唯一屏障。

如果你需要合同级可用性或数据驻留保证,如果负载对延迟敏感,或者你的量级大到这套防护的工程时间比它省下的token更贵,就完全跳过这个方案。对于你还没批准送往第三方端点的受监管数据,这也是错误的模式,无论那个端点多免费。

无论用哪家服务商,值得保留的习惯是:让运行本身回答它花了多少。如果你想找个零成本的地方排练校验车道,该项目的免费额度是个合理的沙盒——只是账本要自己留,让桩服务而不是配额邮件,成为告诉你真相的那个东西。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
国家统计局:今年前三季度,全国居民人均可支配收入34230元,同比名义增长5.3%,农村居民收入增长快于城镇居民

国家统计局:今年前三季度,全国居民人均可支配收入34230元,同比名义增长5.3%,农村居民收入增长快于城镇居民

极目新闻
2026-10-19 10:40:19
2026版《街头霸王》大反派换人,这张脸你绝对见过

2026版《街头霸王》大反派换人,这张脸你绝对见过

赴一场山海啊
2026-10-19 02:26:14
GD家首位小公主诞生!BIGBANG新加坡唱完火速返韩 亲姊平安报喜

GD家首位小公主诞生!BIGBANG新加坡唱完火速返韩 亲姊平安报喜

ETtoday星光云
2026-10-19 17:23:26
整个亚洲都要危险了?日本突然传出坏消息,各国必须高度警惕

整个亚洲都要危险了?日本突然传出坏消息,各国必须高度警惕

林杰论事
2026-10-19 00:42:09
林徽因落选的国徽方案,网友看后感叹:审美确实一绝,但真不合适

林徽因落选的国徽方案,网友看后感叹:审美确实一绝,但真不合适

兴趣知识
2026-07-04 01:34:41
证监会主席吴清:将推出北证50ETF

证监会主席吴清:将推出北证50ETF

新京报
2026-10-19 17:19:24
一语成谶,52岁黄渤确诊入院仅冰山一角,这一病症才是他所恐惧的

一语成谶,52岁黄渤确诊入院仅冰山一角,这一病症才是他所恐惧的

林雁飞
2026-09-04 14:06:23
徐浦大桥违规变道的小车司机,
这事尘埃落定之后要面临 4 个窘境

徐浦大桥违规变道的小车司机, 这事尘埃落定之后要面临 4 个窘境

皮蛋儿电影
2026-10-18 09:01:05
不是被拉下水,是主动投靠!央视曝光一女内鬼,作案细节后背发凉

不是被拉下水,是主动投靠!央视曝光一女内鬼,作案细节后背发凉

铜臭的历史味
2026-10-18 18:29:14
电诈恶魔廖景芳被判死刑!他和农民父母在湖南宁乡老家臭名远扬

电诈恶魔廖景芳被判死刑!他和农民父母在湖南宁乡老家臭名远扬

天气观察站
2026-10-19 07:41:33
张继科直播间放话:女队下一个大满贯,王曼昱比孙颖莎先拿到!她是真强,可一身旧伤才是最大的坎

张继科直播间放话:女队下一个大满贯,王曼昱比孙颖莎先拿到!她是真强,可一身旧伤才是最大的坎

小辉体育
2026-10-18 19:06:31
太硬核了!女孩生理期聊天记录刷屏,男友回复“没遇到我之前你是咋过的”,一句话引爆舆论

太硬核了!女孩生理期聊天记录刷屏,男友回复“没遇到我之前你是咋过的”,一句话引爆舆论

火山詩话
2026-10-17 07:03:59
特朗普公开表示:每个美国人拿到5000美元“特朗普分红”后,必须在美国消费,可以花5000美元在海湖庄园买一个汉堡与一份点心和我共进午餐

特朗普公开表示:每个美国人拿到5000美元“特朗普分红”后,必须在美国消费,可以花5000美元在海湖庄园买一个汉堡与一份点心和我共进午餐

吉刻新闻
2026-10-18 18:59:15
画面不堪入目,地下人奶交易乱象,成年人躺进怀里吃奶的灰色黑产

画面不堪入目,地下人奶交易乱象,成年人躺进怀里吃奶的灰色黑产

易玄
2026-09-12 10:24:46
央八重磅谍战剧《千里江山图》来袭,阵容太豪华,一开播绝对爆火

央八重磅谍战剧《千里江山图》来袭,阵容太豪华,一开播绝对爆火

夸大其词的说
2026-10-19 14:28:10
全红婵近照曝光,瘦了7公斤判若两人,婴儿肥没了网友直呼认不出

全红婵近照曝光,瘦了7公斤判若两人,婴儿肥没了网友直呼认不出

娱说瑜悦
2026-10-19 13:39:42
中方拒签联合声明,俄也不签,美国反华新规生效,欧盟抢着开首枪

中方拒签联合声明,俄也不签,美国反华新规生效,欧盟抢着开首枪

乌克兰小静
2026-10-18 06:59:34
央八谍战大剧来了!顶配阵容太让人期待

央八谍战大剧来了!顶配阵容太让人期待

可乐谈情感
2026-10-19 06:49:14
亲生儿子在父亲再婚后20多年不往来,父亲去世后却回老家要求继承遗产,还起诉继母女儿争房产,法院:未履行赡养义务,分配遗产时应当少分

亲生儿子在父亲再婚后20多年不往来,父亲去世后却回老家要求继承遗产,还起诉继母女儿争房产,法院:未履行赡养义务,分配遗产时应当少分

潇湘晨报
2026-10-19 18:18:29
“大陆警察,有本事来抓我啊!”台独分子,沈伯洋狂妄叫嚣

“大陆警察,有本事来抓我啊!”台独分子,沈伯洋狂妄叫嚣

果妈聊娱乐
2026-10-16 14:39:08
2026-10-19 19:47:00
碳基打工人
碳基打工人
坐标北京,靠咖啡续命,靠小红书下饭的普通人类。
228文章数 88关注度
往期回顾 全部

科技要闻

王晟:近千亿资金涌入后 具身智能开始退烧

头条要闻

女子生龙凤胎起诉已婚董事长确认亲子关系 遭男方起诉

头条要闻

女子生龙凤胎起诉已婚董事长确认亲子关系 遭男方起诉

体育要闻

从NBA退役10年后,他真去警局上班了

娱乐要闻

奚梦瑶回应重返维密:还是很开心的

财经要闻

黄奇帆之子往事:从广微系到魏桥的跳跃

汽车要闻

不知道二代海鸥多好玩? 上赛道跑两圈 很过瘾的

态度原创

游戏
教育
艺术
旅游
军事航空

天下霸唱IP改编影游!《天坑追匪》Demo上架Steam

教育要闻

北京市中小学校园安全知识竞赛收官,获奖名单来了——

艺术要闻

428米、95亿,海南第一高楼开始“戴帽子”了!

旅游要闻

“这点粉丝报什么名”网友报名参选景区体验官被怼懵

军事要闻

泽连斯基:若乌“被要求”举行战时选举 他将竞选连任

无障碍浏览 进入关怀版