類型 | 作用 | 典型場景 | 設定建議 |
---|---|---|---|
maxAttempts | 限制最大重試次數,控制成本與風險 | 短任務(API 呼叫)、高成本任務(付費/重 IO) | 短任務 3–5、高成本 2–3、批次/低優先 5–7;與 initialInterval/backoff/maximumInterval 一起估算總重試時間,需 ≤ 單次/整體 Timeout |
initialInterval | 第一次重試等待時間 | 上游抖動、瞬時錯誤 | 以上游 P95 為基準:短連線/快查詢 100–300ms、人機互動 200–500ms、第三方較慢 1–2s;與 maxAttempts/backoff/maximumInterval 合併估算總重試時間 ≤ 單次 Timeout;越即時 initialInterval 越短、maxAttempts 越少 |
backoffCoefficient | 每次重試逐步延長間隔 | 上游部分故障、做壓力緩釋 | 2.0(指數退避);過大易拖長總時間 |
maximumInterval | 單次等待的上限 | 避免重試等待過長 | 建議 20–60s(短任務 5–15s、第三方較慢 20–60s);須 ≤ 單次 Timeout;與 backoffCoefficient 一起限制總重試時間,避免同時喚醒尖峰 |
nonRetryableErrorTypes | 標記不可重試的錯誤型別 | 驗證失敗、資源不存在、權限問題、業務失敗 | 例如 InvalidInput/InvalidState/PermissionDenied/DuplicateRequest |
原則:
快速檢查:
常見錯誤:
ActivityOptions options = ActivityOptions.newBuilder()
.setStartToCloseTimeout(Duration.ofSeconds(10))
.setScheduleToStartTimeout(Duration.ofSeconds(5))
.setRetryOptions(RetryOptions.newBuilder()
.setMaximumAttempts(5) // 最大重試次數(含首次共最多 5 次)
.setInitialInterval(Duration.ofSeconds(1)) // 第一次重試等待 1 秒
.setBackoffCoefficient(2.0) // 指數退避倍數(1s→2s→4s→…)
.setMaximumInterval(Duration.ofSeconds(20)) // 單次等待上限,避免退避過長
.setDoNotRetry("InvalidInput", "InvalidState") // 不可重試的永久性/業務錯誤型別
.build())
.build();
// 以上述 options 建立活動 stub,Workflow 內呼叫時自動套用
MyActivities acts = Workflow.newActivityStub(MyActivities.class, options);
上一篇談到 Timeout 的觀念,本篇則探討了 Retry 的設計思維,兩者相互搭配,才能兼顧流程的正確性與系統的穩定性。
在這兩個篇幅 Timeout, Retry 都有提到 P95/P99,在此做一個補充。
– 定義:P95 表示 95% 的請求在此時間內完成(P99=99%)。用多數請求的真實 Latency 來定參數,×2 留安全緩衝。
– 取樣:近 7–30 天的實際 Latency,分環境/地區/端點各自量測。
– 視覺化:用直方圖觀察 Latency,比分別盯平均值更有意義。
– 常見誤解:P95/P99 是 Latency 分位數,不是成功率;P99 對樣本量敏感,需足夠時間窗(7–30 天)。
應用:
例子:
Timeout 設得過長,Worker 會被任務佔住;設得過短,任務還沒完成就被中斷。
Retry 次數過多,下游會被重試壓垮;次數過少,暫時錯誤得不到恢復。
流程要可靠穩定,不只在開發時要精心設計,維運過程中也需要持續觀察與調整。
下一篇將談 併發與速率限制,從另一個角度來保護系統資源。