계산대가 없는 동안 끝에 이렇게 적었다.
자동 재시도가 없다. 하니스가 명시적으로 다시 붙였다. 실제 앱이라면 뒤에서 주기적으로 시도해야 하고, 그 주기와 backoff 는 여기서 안 정했다.
이 편이 그 주기를 정한다. 그리고 정하는 김에, 주기를 잘못 정하면 무슨 일이 생기는지를 잰다.
받는 쪽에서 센다
재시도 글은 대부분 거는 쪽 이야기다 — 어떻게 내 요청을 통과시킬까.
이 샘플의 서버는 반대편에 선다. 시도가 몇 번 왔는지, 그리고 그중 몇 번이 같은 200밀리초 안에 몰렸는지를 센다.
/// That second number is the one that matters. A gateway that is briefly down
/// does not care that you tried again. It cares how many of you tried again at
/// the same instant, because that is what keeps it down.
잠깐 죽은 게이트웨이는 당신이 다시 걸었다는 사실에 관심이 없다. 관심 있는 건 몇 명이 같은 순간에 다시 걸었는가다. 그게 계속 죽어 있게 만드는 것이기 때문이다.
급할 때 쓰는 방법
/// Try again immediately. This is what gets written when the retry is added in
/// a hurry, and it is the strategy that turns a short outage into a long one.
class NoBackoff extends Backoff {
@override
int waitBefore(int n) => n == 1 ? 0 : 20;
}

RETRY IMMEDIATELY: 4 callers, 64 attempts total, 4 accepted, peak 18
caller 1 attempt 1: straight away -> DOWN at 12ms
caller 1 attempt 2: after 20ms -> DOWN at 58ms
...
caller 1 attempt 16: after 20ms -> ACCEPTED at 708ms
통과했다. 700밀리초 장애를 넘겼고 네 명 다 결제됐다.
그리고 게이트웨이는 그동안 64번 맞았다.
두 배씩 늘리고, 흔든다
@override
int waitBefore(int n) {
if (n == 1) return 0;
final base = 60 * (1 << (n - 2)); // 60, 120, 240, 480 ...
// Full jitter: anywhere in [0, base]. Spreading matters more than being
// punctual — nobody is waiting on an exact millisecond here.
return _rng.nextInt(base + 1);
}

EXPONENTIAL + JITTER: 4 callers, 25 attempts total, 4 accepted, peak 13
caller 1 attempt 1: straight away -> DOWN at 13ms
caller 1 attempt 2: after 53ms -> DOWN at 70ms
caller 1 attempt 3: after 87ms -> DOWN at 159ms
caller 1 attempt 4: after 143ms -> DOWN at 305ms
caller 1 attempt 5: after 389ms -> DOWN at 697ms
caller 1 attempt 6: after 449ms -> ACCEPTED at 1150ms
같은 장애, 같은 인원, 같은 결과. 네 명 다 결제됐다.
시도는 64번에서 25번. 2.6배 적다.
두 배 늘리는 것과 흔드는 것은 다른 일이다
여기가 이 편이 하고 싶은 말이다.
지수 백오프는 다들 안다 — 60, 120, 240, 480. 지터는 자주 빠진다. 그런데 부르는 쪽이 하나면 지터는 있으나 마나고, 여럿이면 지터가 전부다.
이유는 단순하다. 네 명이 같은 순간에 실패했으면, 지터가 없으면 네 명이 같은 순간에 돌아온다. 60ms 뒤에 넷, 180ms 뒤에 넷, 420ms 뒤에 넷. 게이트웨이는 방금 자기를 넘어뜨린 그 봉우리를 계속 맞는다.
위 로그를 보면 대기가 53, 87, 143, 389, 449로 어느 것도 60·120·240·480이 아니다. 흔들린 값이다.
검증이 그걸 확인한다.
# Jitter must actually produce different waits, otherwise the four callers
# come back together and the whole point is lost.
WAITS=$(grep -o "after [0-9]*ms ->" captures/run.log | sort -u | wc -l | tr -d ' ')
[ "$WAITS" -ge 2 ] || { echo " every wait was identical — jitter is not doing anything"; exit 1; }