Circuit Breaker və Retras
Circuit Breaker və Retras
1) Niyə lazımdır
Şəbəkələr etibarsızdır: gizli pulsasiya, düyünlər düşür, limitlər əldə edilir. Retrajlar qısamüddətli nasazlıqlardan xilas olur və Circuit Breaker sistemi kaskad nasazlıqlardan və «özünü-DDoS» -dən qoruyur. Düzgün vaxtlar və limitlərlə birləşmə SLO-nu saxlayır, quyruq gecikmələrini və "doqquz 'un qiymətini sabitləşdirir.
2) Əsas prinsiplər
İlk vaxtlar, sonra retralar, sonra Circuit Breaker.
Retraim yalnız idempotent əməliyyatları (GET, idempotent açarı ilə təhlükəsiz POST/PUT).
Retrajların büdcəsini ayırın: marşruta orijinal RPS-in 10-15% -ni ≤.
Arızanı lokallaşdırın: bulkhead (ayrı hovuzlar/kvotalar) + rate-limit.
Deqradasiya zamanı - tez uğursuzluq (fail-fast), graceful-degradation/qapaqlar.
3) Retraj semantikası
Nə zaman retraj
Tranzient səhvlər: timeouts, 5xx, şəbəkə əlçatanlığı, 429 ('Retry-After' sonra).
Retraj edilə bilməz: açıq iş səhvləri (4xx ≠ 429), idempotentlik olmadan side-effects (açar olmadan ödəniş).
Strategiyalar
Exponential backoff + jitter (tam və ya vahid): retras sürüsünü hamarlayır.
Max attempts: 1-2 (nadir hallarda 3) - daha çox adətən zərərlidir.
Budget: xidmət və per-request «retry tokens» üçün qlobal retrai/san sayğac.
Hedging (nadir hallarda): t-kvantilindən sonra paralel cüt sorğu (p95) - yalnız ciddi idempotent oxunuşlar üçün.
python base = 100 # ms for attempt in range(1, max_attempts+1):
try:
return call()
except Transient as e:
if attempt == max_attempts: raise sleep_ms = min(cap_ms, base 2(attempt-1))
sleep(random(0, sleep_ms)) # full jitter
4) Taymaut və «sürətli imtina»
Client timeout <upstream timeout: «zombi» sorğuları saxlamaq üçün deyil.
Делите: connect timeout, read timeout, overall deadline.
Tail-aware taymauts: p95/p99 + kiçik ehtiyat hədəf.
Ümumi bir son tarix sahəsi istifadə edin (məsələn, gRPC 'deadline') və zəncir boyunca aşağı atın.
5) Circuit Breaker: necə işləyir
Dövlətlər:- Closed: trafik buraxır, səhvləri/gizli sayır.
- Açıq: Dərhal tez imtina (və ya ehtiyat cavab) verir.
- Half-Open: yoxlama sorğuları; müvəffəqiyyətlə - bağlanır.
- Səhvlər/dəqiqələr N istək/saniyə pəncərəsi üçün X% payını və ya həddən yuxarı p99 payını üstələyir.
- Müvafiq sürüşmə statistikası və minimum həcmi (məsələn, ≥ 50 sorğu).
6) Bulkhead, kvotalar və «bölmək və hakim»
per-upstream və per-fich birləşmələrinin ayrı-ayrı pulları.
In-flight sorğular üçün kvotalar; artıq - tez imtina.
Çatışmazlıqda - aşağı prioritet fich deqradasiyası (feature flags).
7) Perimetr ilə inteqrasiya (Envoy/Istio/Nginx)
Envoy (retry + outlier + CB, ideya):yaml routes:
- match: { prefix: "/api" }
route:
cluster: upstream_api timeout: 2s retry_policy:
retry_on: "connect-failure,reset,retriable-4xx,5xx"
num_retries: 2 per_try_timeout: 600ms retry_back_off: { base_interval: 100ms, max_interval: 800ms }
hedge_policy:
hedge_on_per_try_timeout: true initial_requests: 1 additional_request_chance: { numerator: 5, denominator: HUNDRED } # 5%
clusters:
- name: upstream_api circuit_breakers:
thresholds:
- priority: DEFAULT max_connections: 500 max_requests: 1000 max_retries: 200 outlier_detection:
consecutive_5xx: 5 interval: 5s base_ejection_time: 30s max_ejection_percent: 50
Istio (VirtualService fault/retry, sıxılmış nümunə):
yaml apiVersion: networking. istio. io/v1beta1 kind: VirtualService spec:
hosts: ["payments"]
http:
- route: [{ destination: { host: payments } }]
timeout: 2s retries:
attempts: 2 perTryTimeout: 600ms retryOn: "5xx,connect-failure,refused-stream,reset"
Nginx Ingress (şərhlər):
yaml nginx. ingress. kubernetes. io/proxy-connect-timeout: "2"
nginx. ingress. kubernetes. io/proxy-read-timeout: "2"
nginx. ingress. kubernetes. io/proxy-next-upstream: "error timeout http_502 http_503 http_504"
nginx. ingress. kubernetes. io/proxy-next-upstream-tries: "2"
8) Kitabxana və kod (yığın-snippet)
Java (Resilience4j):java var cb = CircuitBreaker. ofDefaults("psp");
var retry = Retry. of("psp-retry",
RetryConfig. custom()
.maxAttempts(2)
.waitDuration(Duration. ofMillis(200))
.intervalFunction(IntervalFunction. ofExponentialRandomBackoff(100, 2. 0, 0. 5) )//jitter
.retryExceptions(SocketTimeoutException. class, IOException. class)
.build());
Supplier<Response> decorated =
CircuitBreaker. decorateSupplier(cb,
Retry. decorateSupplier(retry, () -> client. call()));
return Try. ofSupplier(decorated)
.recover(BusinessException. class, fallback())
.get();
Go (context deadline + backoff):
go ctx, cancel:= context. WithTimeout(context. Background(), 2time. Second)
defer cancel()
var lastErr error for i:= 0; i < 2; i++ {
reqCtx, stop:= context. WithTimeout(ctx, 600time. Millisecond)
lastErr = call(reqCtx)
stop()
if lastErr == nil { break }
sleep:= time. Duration(rand. Intn(1<<uint(7+i))) time. Millisecond // full jitter time. Sleep(min(sleep, 800time. Millisecond))
}
if lastErr!= nil { return fastFail() }
Node. js (got + p-retry):
js import pRetry from 'p-retry';
await pRetry(() => got(url, { timeout: { connect: 500, request: 2000 } }), {
retries: 2,
factor: 2,
randomize: true,
minTimeout: 100,
maxTimeout: 800,
onFailedAttempt: e => { if (isBusiness(e)) throw e; }
});
9) Retras və SLO büdcəsi
retry tokens daxil edin: hər retray token xərcləyir; hovuz məhdud.
Error-budget ilə əlaqə saxlayın: eşikdən yuxarı burn-rate - retrayları söndürün, CB-ni daha tez açın, deqradasiyanı yandırın.
Kanarya relizləri: Kanaryalarda cəhdləri və tokenləri azaltın.
10) Hedging (ehtiyatlı)
İtirəni ləğv edərək p95 müddətindən sonra əlavə sorğu başlayın.
Yalnız oxu və «təhlükəsiz» idempotent əməliyyatlar üçün; payını məhdudlaşdırın (≤ 1-5%).
Axın yükünün artımını izləyin.
11) Müşahidə
Rate, Error, Duration (p50/p95/p99) marşrutları üzrə RED metriklər.
CB-metriklər: vəziyyət (open/half-open), kəşf tezliyi, qaçırılan/rədd edilən sorğular.
Retrailer: attempts/request, retry-rate, yandırılmış tokenlər.
Perimetri: outlier-ejection, ejection-rate.
Traces: 'retry _ attempt', 'cb _ state', 'hedged = true', 'trace _ id'.
12) Memarlıq ilə inteqrasiya
Bulkhead + CB hər kritik axın.
Növbələr/asinxron: dəli taymaut əvəzinə uzun əməliyyatlar üçün.
Cache/plug: qeyri-kritik fich üçün fail-open.
Avtoskeyl: pis retrajları kompensasiya etmir - əvvəlcə "fırtına 'nı dayandırın.
13) Anti-nümunələr
Zamansız retrasiyalar → «asılmış» konektlər və hovuzların tükənməsi.
Qeyri-idempotent əməliyyatların təkrarlanması (ikiqat silinmə).
cap və jitter olmadan sonsuz eksponensial artım.
Bütün axınlar üçün vahid CB → bütün məhsul üçün nasazlığı sürükləmək.
429/' Retry-After '.
Müştərinin vaxtı axınından daha uzundur (və ya ümumiyyətlə deyil).
«Müalicə» biznes səhvləri retrains.
14) Giriş çek siyahısı (0-30 gün)
0-7 gün
Marşrutları və onların idempotentliyini müəyyən edin.
Zamanlayıcıları (connect/read/overall) təyin edin, minimum retrajları (× 1) və default CB daxil edin.
Əsas axınlar üçün hovuzları/kvotaları (bulkhead) bölün.
8-20 gün
Jitter və qlobal retray büdcəsini, retry-rate alertlərini daxil edin.
Çevrədə outlier-ejection qurmaq, low-prio fich üçün sürətli imtina.
RED + CB/Retry Dashboard, etiketli treys.
21-30 gün
Kanaryalı retraj profilləri (daha az cəhd), game-day «axın yavaş/flap».
Siyasəti sənədləşdirin: kim/nə retrait, limitlər, istisnalar.
p95/p99 və zamanları nəzərdən keçirin.
15) Yetkinlik metrikası
100% marşrutların taymautları və sənədli retraj/SV siyasəti var.
Retry-rate büdcəyə uyğun gəlir (≤ 10-15%), insidentlərdə heç bir sıçrayış yoxdur.
CB bütün hovuz düşmədən əvvəl işləyir; kaskad uğursuzluqlar yoxdur.
Traces/hedging cəhd göstərir; p99 zirvələrdə sabitdir.
Kanarya relizləri «diqqətli» retraj profilindən istifadə edir.
16) Qısa konfiqurasiya nümunələri
Resilience4j YAML (Spring Boot, идея):yaml resilience4j:
circuitbreaker:
instances:
psp:
slidingWindowType: COUNT_BASED slidingWindowSize: 100 minimumNumberOfCalls: 50 failureRateThreshold: 50 waitDurationInOpenState: 30s permittedNumberOfCallsInHalfOpenState: 5 retry:
instances:
psp:
maxAttempts: 2 waitDuration: 200ms enableExponentialBackoff: true exponentialBackoffMultiplier: 2. 0 retryExceptions:
- java. net. SocketTimeoutException
- java. io. IOException
Envoy rate-limit (fikir parçası):
yaml rate_limits:
- actions:
- generic_key: { descriptor_value: "api. payments" }
17) Nəticə
Sabitlik bir intizamdır: taymaut → retrai (jitter və büdcə ilə) → Circuit Breaker + bulkhead/kvotalar və sürətli imtina. Perimetri (outlier-ejection) qurun, RED/CB/Retry dashboard asın, idempotentlik siyasətini düzəldin və biznes SLI-ni unutmayın. Sonra qısa uğursuzluqlar görünməz qalacaq və əsl hadisələr kaskadlı enişlərə çevrilməyəcək.