Timeout, retry, exponential backoff ve circuit breaker nedir? Servisler arası çağrılarda nasıl birlikte kullanılır?

Cevap

Dağıtık sistemlerde bağımlı servisler er geç yavaşlar veya hata verir. Bu dört desen, bir servisin sorununun tüm sisteme yayılmasını (cascading failure) önler.

Timeout

Her ağ çağrısının bir üst süresi olmalıdır. Timeout'suz bir çağrı thread'leri ve bağlantıları sonsuza kadar tutar. Hem connect hem read/request timeout ayarlayın; değer, bağımlılığın normal p99 gecikmesinin biraz üzerinde olmalı. İstek zincirinde deadline aktarımı (kalan süreyi alt çağrılara iletmek) daha da iyidir.

Retry + exponential backoff + jitter

Geçici hatalar (timeout, 503, bağlantı reset) tekrar denenebilir; 400/401/404 gibi kalıcı hatalar denenmez. Yalnızca idempotent işlemler (veya idempotency key taşıyanlar) retry edilmelidir.

import random, time

def call_with_retry(fn, attempts=4, base=0.2, cap=5.0):
    for i in range(attempts):
        try:
            return fn()
        except TransientError:
            if i == attempts - 1:
                raise
            sleep = random.uniform(0, min(cap, base * 2 ** i))  # full jitter
            time.sleep(sleep)

Jitter olmazsa tüm istemciler aynı anlarda tekrar dener ve toparlanmaya çalışan servisi yeniden çökertir. Retry'lar katman katman çarpılır (3 katman x 3 deneme = 27 çağrı), bu yüzden genelde tek katmanda retry yapın veya bir retry budget belirleyin.

Circuit breaker

Bir bağımlılığın hata oranı eşiği aşınca çağrıları bir süre hiç yapmadan hemen başarısız kılar.

DurumDavranış
ClosedNormal; hatalar sayılır
OpenÇağrılar yapılmaz, hemen hata veya fallback döner
Half-openSüre dolunca birkaç deneme isteği geçer; başarılıysa Closed, değilse tekrar Open

Faydası: sorunlu servise yük bindirmeyi bırakır, onun toparlanmasına izin verir ve çağıranın kaynaklarını (thread, bağlantı) korur.

Birlikte kullanım

Timeout her çağrıyı sınırlar → retry geçici hataları emer → circuit breaker kalıcı arızada retry fırtınasını keser → fallback (cache'teki son değer, varsayılan yanıt) kullanıcı deneyimini korur. Ek olarak bulkhead (bağımlılık başına ayrı thread/connection havuzu) bir bağımlılığın tüm kaynakları tüketmesini engeller.

Araçlar: Java'da Resilience4j, .NET'te Polly (Microsoft.Extensions.Http.Resilience), Node.js'te opossum; service mesh'ler (Istio) bunları altyapı seviyesinde de sunar.

  1. Mesaj kuyruğu (RabbitMQ, Kafka) ne zaman kullanılır?ZorSistem TasarımıBackend
  2. Monolith ile mikroservis mimarisi arasındaki fark nedir? Mikroservislere ne zaman geçilmeli?ZorSistem TasarımıBackend
  3. CAP teoremi nedir? Gerçek sistemlerde nasıl yorumlanır?ZorSistem TasarımıBackend
  4. Dikey ve yatay ölçekleme arasındaki fark nedir?KolaySistem TasarımıFull Stack
  5. Hangi cache stratejilerini biliyorsunuz?OrtaSistem TasarımıFull Stack
  6. REST ile GraphQL arasındaki farklar nelerdir?OrtaSistem TasarımıFull Stack

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle