Day 12 講過失敗要局部重試,但沒細講「重試前該等多久」。立刻重試聽起來反應最快,但如果失敗原因是對方暫時過載,立刻重試只會讓對方更喘不過氣,甚至讓所有並行的重試同時湧入,讓情況更糟。
tries = 0
while True:
try:
await download(segment)
return
except Exception as e:
tries += 1
if tries >= 10:
log_failure(segment, e)
return
await asyncio.sleep(10) # 固定等 10 秒
這個選擇談不上完美,但在這個情境下是合理的:片段下載的並行數量本身就被 ThreadPoolExecutor 的 max_workers 限制在一個不大的數字(前面提過是 10),不太會出現「數千個請求同時重試、集體打垮對方」這種需要指數退避加抖動才能緩解的場景。策略選得對不對,要看情境的並行規模,不是有沒有用上聽起來比較講究的演算法。
如果情境換成「面對一個公開 API、有明確的速率限制、大量使用者共用同一個服務」,固定間隔重試就容易出問題——所有失敗的請求都在同一個時間點集體重試,反而製造出一波新的尖峰負載。這種情境下,指數退避加上隨機抖動能有效把重試的時間點打散,避免形成新的尖峰。
你的專案裡的重試邏輯用的是固定間隔還是指數退避?這個選擇是刻意評估過並行規模跟情境需求做的,還是照著某個範例程式碼直接抄過來的?
明天講合併前的驗證:怎麼先確認片段真的湊齊了,再開始合併。