目錄(33 節)

TTS 重試邏輯點寫先啱?錯誤分類同退避策略指南

先分類、後重試、降級收尾——三段式錯誤處理嘅完整指南。

— 港嘢內容團隊約 11 分鐘粵語TTS錯誤處理API教學後端
分享:

一句答你: 重試嘅鐵律係「分類先重試」:400/401/403 類係你嘅 payload 或帳務問題,重試幾多次都一樣;429 照 Retry-After 等;5xx 同網絡錯誤先值得指數退避重試——盲 retry 只會令限流同日誌更難睇。

Key Takeaways

  • 錯誤分三類:即刻改(4xx 參數/帳務)、照指示等(429)、退避重試(5xx/網絡)
  • 429 有兩種:每分鐘限流(Retry-After 話你知等幾耐)同在途上限(等一個任務完成或取消舊嘅)
  • 限流只計「成功嘅請求」——盲重試唔會令你更接近成功
  • 同步接口 503 pool_cold 係設計行為,後備路徑係任務式
  • 音頻網址過期唔使重生成:再 poll 一次任務就有新網址
  • 最平嘅重試係提交前驗證:500 字符、emotion 合法值、聲線模式三選一

開波前:將錯誤分三類

任何重試邏輯嘅第一步唔係寫 retry loop,係分類。根據公開規格(觀察日期 2026-10),港嘢 API 錯誤可以用 HTTP 碼加穩定 error 碼分成三類:

類別代表錯誤正確反應
A:重試冇用400 參數錯、401 金鑰問題、403 額度/權限改 payload/換 key/處理帳務,先至再嚟
B:照指示等429(限流/在途上限)讀 Retry-After/等任務釋放名額
C:退避重試5xx 暫時性、網絡錯誤指數退避,設重試上限

九成重試邏輯嘅事故,都係將 A 類錯誤塞咗入 C 類嘅 loop 度——一秒一次咁撞 400,撞到天荒地老。

A 類:重試冇用嘅錯誤

400:payload 有問題

高頻幾個:text 超過 500 字符(成個拒絕、唔會截短)、response_format 唔係 mp3/wav、emotion 唔喺九個合法值、聲線模式三選一(voice/design/clone)多選或漏選、批量超過 25 項或任何一項無效(全有或全無拒收)、聲音複製缺逐字稿。全部係提交前一句 if 就捉到嘅嘢——客戶端驗證先係最平嘅修復。

401/403:金鑰同帳務

  • 401 invalid_or_expired_token:金鑰無效、過期、被撤銷——換 key,唔使諗
  • 403 insufficient_scope:缺權限(聲音複製要 tts:clone 權限)——去金鑰管理加範圍,或者換把有權嘅 key
  • 403 monthly_cap_reached:金鑰月度字符上限到(回應有 used)——上限係你開 key 時設定嘅,調高佢,或者等下個月度週期重置
  • 403 batch_requires_pro:批量係專業/工作室功能——升方案,或者拆返做單項提交

404:任務唔存在

invalid_job_id(格式唔係 UUID)或者 job_not_found(冇呢個編號,或者唔係呢把 key 嘅任務)——都係你嘅記錄問題,重試冇意義。

B 類:429 兩兄弟,處理方法唔同

限流:rate_limit_exceeded

每分鐘限流(預設 60 次/key,開 key 可調)係滑動 60 秒窗口,只計成功嘅 billable 請求。撞到會回:

HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1799167200

正確反應就係照 Retry-After 等夠鐘先重交(回應入面都有 retry_after)。呢啲 header 出現喺提交接口嘅 202 同 429 回應。

在途上限:in_flight_limit_reached

每個方案有並行在途任務上限:免費 3、入門 5、專業 10、工作室 20。撞到回應會帶 limit 同 active。呢個唔係「等幾多秒」嘅問題,係「等一個任務離場」嘅問題:

  • 等:你嘅輪詢 worker 遲早 poll 到 completed,名額自動釋放
  • 趕:過期唔要嘅任務(用家已經行咗嘅互動)用 DELETE /v1/audio/jobs/{id} 取消,即刻騰位
  • 提防:批量一次過會產生多個任務,每個都佔在途名額——批量提交前記得預留

C 類:值得退避重試嘅錯誤

5xx:暫時性問題

幾個 503 碼:pool_cold(同步接口資源未預熱——fail closed 設計,回應 hint 直接提你轉任務式)、voice_gallery_unavailable、jobs_unavailable、audio_history_unavailable。全部係「等一陣再嚟」類:退避重試,同步接口就順便行任務式後備。

網絡錯誤

分兩個位:

  • 查詢斷線:冇後果,直接再 poll(讀取唔計限流)
  • 提交斷線:有少少麻煩——你唔知後端收咗未。穩陣做法:短退避後重提交,同時接受「可能重複佔用限流窗口」嘅成本(限流只計成功請求,重複嘅只係佔窗口唔係重複生成);提交成功即刻記任務編號,避免下次再盲試

一個減低提交斷線痛感嘅習慣:提交請求帶自己嘅日誌標記(業務參考號寫入請求記錄),斷線重試嗰陣對返同一個標記——第日對帳,先分得清邊次係重複、邊次係唯一。

退避模板(可以抄)

MAX_RETRIES = 3
for attempt in 1..MAX_RETRIES:
    result = submit()
    if 429: 等 Retry-After 秒;continue                      # B 類:照指示
    if 5xx or network: 等 (2^attempt + 隨機 0–1 秒);continue  # C 類:指數退避+jitter
    if 4xx: 停——入死信記錄,人手/驗證層跟                     # A 類:重試冇用
    if 202: 記任務編號;break

三個參數要設:重試上限(3 次係合理起點)、jitter(防同時重試整齊撞)、死信記錄(A 類要有人見到)。呢個模板嘅精神係「分類決定命運」:同一個 exception handler 應付所有錯誤嘅寫法,就係 429 風暴同無限 loop 嘅溫床。將三類錯誤寫成三條明確分支,讀 code 嘅人一睇就明,出事嗰陣一睇日誌就知行咗邊條枝。

提交冪等與對帳:重試嘅最後一塊拼圖

重試講到尾,最怕嘅係「唔知一件事做咗未」。兩個防線:

  • 提交側冪等:你自己嘅業務記錄要有狀態機——「待提交→已提交(有任務編號)→已終態」。重試邏輯只喺「待提交」狀態先會出手,見到「已提交」就轉去輪詢,唔會交多一份
  • 定期對帳:每日一次,對齊兩本帳——你系統入面「已提交」嘅任務,同實際終態記錄。有「已提交」但永遠冇終態嘅,就係漏網,出警報

呢兩樣唔係華麗架構,係兩張表加一個定時任務,但佢哋係重試邏輯嘅地基:冇狀態機嘅重試,每次都係賭博。

監察指標:重試系統嘅體溫計

重試邏輯上咗線,點知佢健唔健康?四個指標:

指標健康樣警號
重試成功率重試之後大半過到重試都救唔返,即係 C 類越嚟越多
錯誤分佈4xx 佔比穩定4xx 突升=你嘅 payload 或者模板有變
限流貼近度X-RateLimit-Remaining 長期有剩長期貼 0=要調限流或者升方案
死信量長期接近零持續累積=有問題冇人跟

每日一眼,一星期一覆盤,足夠。監察嘅目的唔係靚儀表板,係令問題喺細嗰陣就現形。

網絡層面:timeout 都要分級

重試邏輯嘅近親係 timeout 設定,同樣要分場景:

  • 查詢(poll):timeout 設短(幾秒級)——poll 唔計限流,斷咗再 poll 冇成本
  • 提交:timeout 設長少少——但要明白長 timeout 嘅代價係你等,唔係佢快
  • 下載:跟檔案大小預期設——音頻檔唔大,一般幾十秒綽綽有餘
  • 全球統一一個 timeout:唔好。唔同工序時間尺度唔同,一刀切唔係太敏感就係太遲鈍

timeout 撞線同 5xx 同類處理:計入 C 類,退避重試,次數計入同一個上限。

一個場景演練:批量任務嘅完整錯誤處理

想像你交一批 20 句嘅教材旁白,行一次可能撞到嘅錯,逐步睇正確反應:

  1. 提交前:自查 20 項每項 ≤500 字符——發現第 13 句 620 字符,按標點拆開。呢一下已經避咗一次 invalid_items 成批拒收
  2. 第一次提交:撞 403 batch_requires_pro——原來你係入門方案。決策:改行逐項提交(批量係方案功能唔係故障,唔使重試)
  3. 逐項提交中:第 8 項撞 429 rate_limit_exceeded,Retry-After 話等 30 秒——排程器照等,其餘項目照常排
  4. 輪詢中:第 3 項 failed——檢查發現稿面有一個半形亂碼符號,清走之後單獨重交呢一項
  5. 下載時:其中一條音頻網址過咗時效——re-poll 攞新網址,唔使重生成

成個過程嘅重點:冇一步係盲 retry——每個錯都有分類、有對應動作,全部錯誤最後都有去處。呢個先係重試邏輯嘅完全體。

日誌要記咩(第日急救靠佢)

每次提交同重試,記低五樣嘢:

  • 時間戳
  • 請求摘要(邊個業務參考號、幾多字符——唔使記全文,記個標記就夠)
  • HTTP 碪+error 碼
  • 重試次數
  • 終局(成功嘅任務編號/放棄入死信)

有呢五樣,第日「點解呢批少咗三條」嘅問題,五分鐘內有答案;冇呢五樣,就係考古。

金鑰輪換期間嘅錯誤

轉 key 嘅過程特別多 401:舊 key 已撤、新 key 未生效、或者兩邊權限範圍唔一致。兩個做法:

  • 輪換用「先加後減」:新 key 開好、驗證行通,先撤舊 key
  • 401 唔好入 retry loop,但要入警報——佢通常代表配置問題,唔係暫時性問題

一個 429 風暴嘅解剖

睇一個真實感十足嘅事故劇本,同佢點樣可以避免:

事發:一個數據遷移腳本要生成 3,000 句旁白。開發者寫咗「撞 429 就 sleep 1 秒再試」。結果:限流窗口係 60 次/分鐘,佢每秒試一次,一小時內發出 3,600 次請求、通過不足 60 次,日誌爆晒,進度近乎零。

解剖:三個錯疊埋一齊——

  1. 重試間隔(1 秒)遠細過窗口長度(60 秒),注定大部分請求撞牆
  2. 冇讀 Retry-After——平台其實話咗你知要等幾耐
  3. 冇提交節流——正確做法係一開始就控制喺「每分鐘 60 次以內」嘅節奏提交,根本唔會撞

正解:節流先行(提交節奏貼住限流額度),重試做後備(照 Retry-After)。節流係預防,重試係補救——用補救代替預防,代價就係成個鐘嘅空轉。

error message 都要識讀

error 碼係分類用,message 就係細節。兩個例子:

  • {"error":"text_too_long","message":"text exceeds 500 characters."}——碼話你知類別,message 話你知邊個參數、邊條線
  • 403 monthly_cap_reached 嘅回應帶 used——即係話你知而家使咗幾多,方便你對返自己嘅上限設定

所以日誌要連 message 一齊記。日後排查,碼幫你分類,message 幫你定位。

降級策略嘅三層設計

重試邏輯嘅盡頭係降級——重試完都唔得,你嘅系統做咩?

  1. 第一層:縮細需求——長句拆短再試,輸入細咗,流轉自然順
  2. 第二層:換模式——同步撞 503 轉任務式;批量撞 403 轉逐項;複製聲線唔得就轉圖庫聲線
  3. 第三層:改交付——文字代替語音、提示稍後再試、或者排入下一個批次

三層都預咗,任何一時嘅波動都唔會令你嘅業務即時停擺——語音生成應該係你流程入面「有後備」嘅一環,唔係單點。

特殊個案:音頻網址過期

呢個唔係錯誤,係時效:completed 任務嘅預簽網址,入庫嘅 1 小時、直出嘅 7 日。過期咗唔使重生成——再 poll 一次嗰個任務,攞條新網址就得。所以下載邏輯應該係「載唔到 → 再 poll → 再載」,唔係「載唔到 → 重交任務」。

提交前驗證:最平嘅重試係唔使重試

一份提交前檢查表,可以食咗 A 類嘅大部份:

  • text:1 至 500 字符
  • 聲線:voice/design/clone 三選一
  • emotion:九個合法值入面揀(happy、sad、angry、fearful、disgusted、surprised、neutral、excited、gentle)
  • 格式:mp3 或 wav
  • 批量:≤25 項,每項先各自過晒上面檢查
  • 同步捷徑:≤300 字符、唔帶字幕、唔用複製聲線

完整錯誤碼表逐個碼嘅對策,睇TTS API 錯誤碼大全;第一個請求點發起,睇粵語 TTS API 快速上手;成個 API 嘅全貌同角色定位,睇廣東話 TTS 完全指南。批量分批策略另文有(批量生成工作流)。

冇終態嘅任務:卡死咗點算?

理論上每個任務都會去到終態,但你嘅系統要預「萬一」:任務提交後超過合理時間(例如你場景嘅正常終態時間嘅十倍)仍然未見終態,就將佢標記為「可疑」,出警報;確定唔要嘅,用取消接口主動終結,釋放在途名額。唔好畀一個殭屍任務長期佔住名額——在途上限係稀缺資源。

常見問題 FAQ

重試幾多次先合理?

C 類 3 次係好起點(指數退避加 jitter),A 類 0 次——佢哋應該去死信記錄。B 類唔算「重試」,佢係「照指示等」,理論上可以一直等,因為每次都係新窗口。

撞限流可唔可以即刻再試一次博下?

唔好。窗口係滑動嘅,即刻重試好大機會再撞,仲要燒你嘅日誌同資源。Retry-After 係平台計好俾你嘅答案,照跟最慳。真係急,就檢查下自己係咪有重複提交嘅 bug——長期撞限流多數唔係運數差,係提交側冇節流。

在途上限撞咗,取消邊個任務好?

最舊嗰啲「等緊都冇人聽」嘅:例如用家已經離開嘅互動回合。你自己嘅業務記錄(任務編號 ↔ 參考號映射)會話你知邊啲仲有價值。

提交嗰下網絡斷咗,會唔會重複收費?

計費跟任務本身,唔係跟你睇唔睇到回應;真正風險係你重複提交而多生一份。所以任務編號即刻入庫嘅習慣好重要,重要流程先至值得加「提交前查重」邏輯。

5xx 重試都係 5xx,幾時放棄?

重試上限到(例如 3 次)就放棄入死信,同時觸發你嘅降級(例如出文字唔出聲、或者提示稍後再試)。平台側暫時性問題通常短命,但長命就唔係你嘅重試可以解決。放棄唔係認輸——係將問題由「自動重試」移交去「人手同監察」,各有各嘅崗位。

呢套分類適用於其他 API 嗎?

思想通用,碼表唔通用——每個平台嘅錯誤語義唔同,A/B/C 分類要按你自己用嗰個服務嘅文件重砌。不過「先分類、後重試、降級收尾」呢個三段式,基本上任何有錯誤碼嘅 API 都適用;你只要將本文嘅碼表換成對應平台嘅碼表,骨架原封不動。可以話,呢篇教你嘅唔係一張表,係一個砌表嘅方法。

點知自己係咪長期貼住限流?

每次提交記低 X-RateLimit-Remaining,日尾睇分佈——長期貼 0 就唔使諗重試,直接開金鑰調高限流或者升方案(在途上限同步升級)。

[!CTA]

俾你嘅重試邏輯行一次真流程

免費開戶每月 5,000 字符加沙盒金鑰,撞錯都唔肉痛,試到順為止。

相關文章