要点: 耐障害性は再試行回数を増やすことではなく、時間と資源に上限を持たせることから生まれます。
この記事の用語: Circuit Breaker:失敗中のサービス 呼び出しを一時停止する仕組み。Bulkhead:資源を分離して障害波及を防ぐ設計。
現場の課題
Timeoutがなければ資源を長く保持し、複数層の再試行は下流呼び出しを増幅します。共有接続プールでは、一社の遅延が全体の資源を枯渇させます。
遅い依存サービスは接続を使い切り、無制限再試行は弱っている下流へさらに負荷を加えます。呼び出しごとに期限、試行、資源プールを分けます。
設計と実装
- 処理全体の期限を伝播し、残り時間がなければ下流呼び出しを止めます。
- 冪等な操作の一時エラーだけを、少ない回数と待ち時間の段階的増加付きで再試行します。
- 依存サービスごとに接続と同時実行数を分離し、キューが無限に増える前に拒否します。
実装例
remaining = request.deadline - now()
if remaining < minimumUsefulTime: return degraded()
with bulkhead.acquire(timeout = 20ms):
return retry(max = 2, jitter = true) {
vendor.call(timeout = min(300ms, remaining))
}本番導入の進め方
現状の遅延と試行数を測り、まず明示Timeoutだけを追加します。次にプール分離、限定再試行、観測のみのCircuit Breakerという順で導入します。
まとめ
壊れにくい外部連携は、障害を既知の上限内へ閉じ込め、健全な部分の能力を守ります。
