Tags: distributed-systems, microservices, resilience, circuit-breaker, retry, ratelimit
Level: intermediate
TL;DR: Pattern architetturali essenziali per garantire alta disponibilità, isolamento dei guasti e degradazione controllata nei sistemi distribuiti.
Circuit Breaker previene chiamate ripetute a servizi degradati gestendo tre stati: Closed, Open e Half-Open.
Retry con exponential backoff e jitter evita l'effetto thundering herd su servizi a valle in ripresa.
Bulkhead isola risorse computazionali, thread pool o code per impedire che un singolo guasto saturi l'intero sistema.
Rate Limiting e Throttling proteggono le API dal sovraccarico respingendo il traffico eccedente con HTTP 429.
Timeout perentori su ogni chiamata sincrona impediscono l'esaurimento dei socket e il blocco indefinito dei worker.
Fallback garantisce una degradazione controllata restituendo cache, dati parziali o valori di default sicuri.
Idempotency key sulle operazioni di mutazione rende sicure le ritrasmissioni automatiche in caso di transient error.
Health check liveness e readiness guidano l'instradamento del traffico ed escludono nodi instabili dal pool.
Q: Come decidi quando applicare un Retry rispetto a un Circuit Breaker?R: Uso il Retry con backoff per errori transitori come brevi timeout di rete. Se gli errori persistono oltre una soglia prefissata, attivo il Circuit Breaker per fail-fast immediato ed evitare di sovraccaricare il servizio a valle.
Q: Perché il jitter è fondamentale quando si implementano i retry nei client distribuiti?R: Senza jitter, tutti i client che falliscono nello stesso momento ritentano sincronizzati agli stessi intervalli. L'aggiunta di casualità disperde i picchi di traffico ed evita di causare un thundering herd.
Q: Come gestisci il pattern Fallback senza restituire dati inconsistenti all'utente?R: Restituisco dati degradati solo per letture non critiche servite da cache locale o stale replica. Per scritture o transazioni monetarie rifiuto esplicitamente l'operazione restituendo un errore chiaro.
Retry infiniti senza contatore massimo che esauriscono socket e bloccano thread di esecuzione.
Applicare retry automatici su endpoint non idempotenti, causando mutazioni o addebiti duplicati.
Circuit breaker configurati con soglie di errore basate su numeri assoluti invece che su percentuali relative al volume.
Mancanza di timeout dedicati per connection timeout e read timeout nei client HTTP/gRPC.
Fallback che nascondono errori critici restituendo risposte vuote non monitorate da metriche e allarmi.
```interface RetryConfig {
maxRetries: number;
baseDelayMs: number;
maxDelayMs: number;
}
async function retryWithBackoffAndJitter<T>(
operation: () => Promise<T>,
config: RetryConfig
): Promise<T> {
let attempt = 0;
while (true) {
try {
return await operation();
} catch (error) {
attempt++;
if (attempt > config.maxRetries) {
throw error;
}
const exponentialDelay = config.baseDelayMs * Math.pow(2, attempt - 1);
const cappedDelay = Math.min(exponentialDelay, config.maxDelayMs);
const jitter = Math.random() * cappedDelay;
await new Promise((resolve) => setTimeout(resolve, jitter));
}
}
}
```
[ ] Configurazione differenziata tra readiness probe e liveness probe in Kubernetes.
[ ] Implementazione del token bucket algorithm e sliding window counter per rate limiting.
[x] Transizioni di stato del Circuit Breaker tra Closed, Open e Half-Open.
[x] Utilizzo delle Idempotency Keys per richieste POST di pagamento.
Release It! Design and Deploy Production-Ready Software (Michael T. Nygard)
Microsoft Cloud Design Patterns: Circuit Breaker, Retry, Bulkhead, Throttling