Що таке патерн Retry і як його правильно використовувати
Structured Java interview answer with junior, middle, and senior-level explanation.
🟢 Junior Level
Retry — автоматичний повторний виклик сервісу при тимчасовій помилці.
Виклик 1 → помилка (timeout)
Retry 1 → помилка (timeout)
Retry 2 → успіх! ✅
Навіщо: Тимчасові помилки трапляються часто (мережа, таймаут, перевантаження). Retry дає сервісу час відновитися.
🟡 Middle Level
Resilience4j Retry
RetryConfig config = RetryConfig.custom()
.maxAttempts(3) // 3 спроби
.waitDuration(Duration.ofSeconds(1)) // чекати 1 сек між спробами
.retryExceptions(TimeoutException.class, ConnectException.class)
.build();
Retry retry = Retry.of("backend", config);
Supplier<String> decorated = Retry.decorateSupplier(retry,
() -> backendService.call());
Exponential backoff
RetryConfig config = RetryConfig.custom()
.maxAttempts(5)
.waitDuration(Duration.ofMillis(500))
.intervalFunction(IntervalFunction.ofExponentialBackoff(500, 2.0))
.build();
// 500 = початкова затримка (мс), 2.0 = множник (exponential).
// 500ms → 1000ms → 2000ms → 4000ms ...
// Спроби: 500ms → 1s → 2s → 4s → 8s
Типові помилки
- Retry для всіх помилок:
404 Not Found → retry безглуздий 500 Internal Error → retry може допомогти Рішення: retry тільки для retryable помилок
🔴 Senior Level
Retry з jitter
// Jitter запобігає thundering herd
// Thundering herd — коли безліч клієнтів одночасно повторюють виклик,
// створюючи новий пік навантаження. Jitter «розмазує» повторні виклики в часі.
Random random = new Random();
long waitTime = baseDelay + random.nextInt((int)(baseDelay * 0.1)); // jitter 10% від delay
Production Experience
Spring Retry:
@Retryable(
value = {RetryableException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2)
)
// @Recover — метод, що викликається коли усі retry вичерпані.
// Сигнатура: той самий тип значення, що повертається + Exception як перший параметр.
public String callService(String input) {
return restTemplate.getForObject(url, String.class);
}
@Recover
public String recover(RetryableException e) {
return "fallback";
}
Best Practices
✅ Exponential backoff
✅ Jitter для запобігання thundering herd
✅ Retry тільки для retryable помилок
✅ Ліміт спроб
✅ Fallback після усіх retry
❌ Retry для 4xx помилок
❌ Без backoff
❌ Без ліміту спроб
❌ Retry для неідемпотентних операцій
🎯 Шпаргалка для співбесіди
Обов’язково знати:
- Retry — автоматичний повторний виклик при тимчасовій помилці (timeout, network)
- Exponential backoff: 500ms → 1s → 2s → 4s — дає сервісу час відновитися
- Jitter додає випадковість для запобігання thundering herd
- Retry тільки для retryable помилок (TimeoutException, ConnectException)
- 4xx (Not Found, Bad Request) — retry безглуздий, сервіс не полагодиться
- maxAttempts обов’язковий — нескінченний retry = hang
- Fallback після вичерпання усіх спроб
Часті уточнюючі питання:
- Що таке thundering herd? Безліч клієнтів одночасно повторюють виклик — jitter «розмазує» повтори.
- Які помилки retryable? Timeout, connection refused, 5xx. НЕ retryable: 4xx, business exceptions.
- Exponential backoff формула? delay = baseDelay * multiplier^attempt, наприклад 500ms, 1s, 2s, 4s.
- Spring Retry vs Resilience4j? Spring Retry простіший, Resilience4j гнучкіший (bulkhead, circuit breaker, time limiter).
Червоні прапорці (НЕ говорити):
- “Retry для всіх помилок” — ні, 404 retry безглуздий
- “Retry без ліміту — надійність” — ні, нескінченний retry = hang системи
- “Jitter не потрібен, сервери впораються” — без jitter thundering herd
- “Retry = ідемпотентність не важлива” — критична, duplicate request можливий
Пов’язані теми:
- [[20. Що таке exponential backoff]]
- [[17. Як забезпечити відмовостійкість мікросервісів]]
- [[5. Що таке патерн Circuit Breaker]]
- [[4. Що таке компенсувальні транзакції]]
- [[15. Як організувати комунікацію між мікросервісами]]