---
title: 'Hız Sınırları ve Yeniden Deneme'
source: 'https://academia.sh/tr/kurslar/model-apileri/hiz-sinirlari-ve-yeniden-deneme'
course: "Model API'leri ile Uygulama Geliştirme"
language: tr
updated: '2026-08-17T18:06:37+00:00'
license: 'CC BY-SA 4.0'
---

# Hız Sınırları ve Yeniden Deneme

Aynı 160 kurgu talebin iki yük düzeyinde üç politikayla koşturulması: düzeneksiz istemci her iki yükte de 0,8562 tamamlıyor ve hiç hız sınırına takılmıyor. Hafif yükte yeniden deneme tamamlamayı 1,0000'a çıkarıyor, bedeli 25 ek çağrı ve 1209 belirteç. Ağır yükte aynı düzenek işi bozuyor: sabit aralıklı deneme 0,8000'e düşüyor ve 151 hız sınırı reddi üretiyor, geri çekilmeli deneme 0,8750 ile düzeneksizin 0,0188 üstünde kalıyor ama iki koşum farkı da 0,0188. Aynı sınırı paylaşan etkileşimli akış 0,9500'den 0,8667'ye iniyor: yeniden deneme kendi işini kurtarırken başkasının işini bozuyor.

Önceki sekiz derste arayüzün ne sunduğu ölçüldü: konuşma durumunun taşınması, yanıt akışı,
araç çağrısı, yapılandırılmış çıktı kipi, çok kipli girdi, gömme arayüzü, uyumlu arayüz katmanı
ve toplu çağrı. Hepsinin ortak bir sessiz varsayımı vardı: **çağrı başarılı oldu.** Sayılan her
belirteç, ödenen ve karşılığı alınan bir belirteçti.

Bir üretim hattında bu varsayım tutmaz. Çağrı reddedilir, yarıda kesilir, hiç yanıt vermez.
Bunların karşılığı bilinen bir yordamdır: yeniden dene. Yeniden deneme M16'nın dayanıklılık
kursunda ve M19'un çalışma zamanı kursunda ölçüldü; yordamı burada tekrarlanmaz. Bu derste
eklenen tek şey, çağrının **pahalı ve belirsiz** olmasından gelir: her deneme girişi bir kez daha
öder, her deneme aynı hız sınırına bir çağrı daha yükler, ve yarıda kesilen bir çıktı hiçbir işe
yaramadan belirteç harcamıştır. Sorunun kendisi budur — yeniden deneme, düzelttiği şeyin
kaynağını besler.

- **UK1.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Talepler, kalıplar ve ağ
  davranışı **kurgudur**, tohum **20260218**.
- **UK2.** Zaman **adım** ile sayılır, ham süre yazılmaz. Bir adım istemcinin bir gönderim turudur.
- **UK3. Hız sınırı kayan pencerede okunur ve reddedilen çağrılar da sayılır:** son üç adımda
  yapılan toplam çağrı yirmi dördü aşarsa çağrı reddedilir. Reddi saymayan bir uç noktada aşağıda
  ölçülen fark küçülür; bu davranış bir varsayımdır ve sonucu belirler.
- **UK4.** Reddedilen çağrı **belirteç harcamaz**. Kabul edilen her çağrı girişini tam öder.
- **UK5.** İki içerik başarısızlığı vardır: **zaman aşımı** (çıktı başlamadan kesilir, giriş
  ödenir) ve **yarım çıktı** (giriş ile bir belirteç çıkış ödenir, yanıt okunamaz).
- **UK6.** İstemci bir adımda en çok on iki çağrı gönderir; bir istek en çok dört kez denenir.
- **UK7. İki iş yükü aynı sınırı paylaşır:** 160 kayıtlık toplu sınıflandırma ve iki adımda bir
  gelen **etkileşimli** durum sorgusu. Etkileşimli sorgunun gecikme bütçesi bir adımdır.
- **UK8.** Yük, patlama sırasında adım başına gelen istek sayısıdır: **hafif üç, ağır altı**.

## Çağrının Üç Başarısızlığı ve Bedeli

Benzetici bu konuda bir şey daha taşır: **ağ davranışı**. Aynı istem, pencerenin doluluğuna göre
reddedilebilir; kabul edilse bile yanıt yarıda kesilebilir. Üç sınıfın ayrı ayrı sayılması
gerekir, çünkü **bedelleri farklıdır**.

```python
# BENZETICI -- KURGUDUR. Gercek bir uc nokta cagrilmaz; ag davranisi da ders
# icinde yazilir. Talepler ve kaliplar kurgudur, tohum 20260218.
TOHUM, M32 = 20260218, 0xFFFFFFFF
KOTA, KADIM = 24, 3          # kayan pencerede sayilan cagri / pencere adimi
ESZAMAN, BUTCE, EN_COK = 12, 140, 4


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def belirtecle(m):           # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


def izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KALIP = [("bu ayki fatura tutari gecen aya gore cok yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("fatura ayrintisini nereden gorebilirim", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("ariza kaydi actim ama ekip gelmedi", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("sayac uzerindeki endeks ile fatura ayni degil", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("tarife degisikligi icin ne yapmam gerekiyor", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti"),
         ("aksamdan beri kesinti yasiyoruz", "kesinti")]
EK = ["ayrica gecen ay tarife degisikligi de yapilmisti",
      "kayit numarasini ekliyorum ekip hala gelmedi",
      "odeme gorunmuyor ama dekont elimde duruyor",
      "duyurulari takip ediyorum yine de bilgi alamadim"]
TALEP = []
for i in range(160):         # 160 KURGU destek talebi
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    m = [x for x in KALIP if x[1] == k][int(r() * 3)][0]
    TALEP.append({"no": 4001 + i, "konu": k,
                  "metin": m + (" " + EK[int(r() * 4)] if r() < 0.34 else "")})

KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"]
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "borc": "odeme",
      "ariza": "ariza", "bozuk": "ariza", "calis": "ariza", "akmiy": "ariza",
      "sayac": "sayac", "endek": "sayac", "okuma": "sayac", "tarif": "tarife",
      "birim": "tarife", "abone": "tarife", "basam": "tarife", "kesin": "kesinti",
      "duyur": "kesinti", "mahal": "kesinti", "dekon": "odeme", "sikay": "sikayet"}
YONERGE = ("Talebi su etiketlerden birine ata: fatura , ariza , sayac , tarife , "
           "kesinti . Yanit olarak tek etiket yaz . ")
SUNUCU = {"gecmis": []}


def istemi(t):
    return YONERGE + f"Talep {t['no']} : {t['metin']}"


def etiketle(bel):           # en olasi secim; adayi daraltan sey etiket kumesidir
    aday = [k for k in KAVRAM if k[:5] in bel]
    p = {k: 0.15 for k in (aday if len(aday) >= 3 else KAVRAM)}
    for t in bel:
        if IZ.get(t) in p:
            p[IZ[t]] += 1.0
    return max(sorted(p), key=lambda a: p[a])


def cagir(istem, adim, deneme=0, tohum=TOHUM):
    """KURGU uc nokta. Hiz siniri kayan pencerede REDDEDILENLER DAHIL sayar."""
    g = SUNUCU["gecmis"]
    while len(g) <= adim:
        g.append(0)
    g[adim] += 1
    if sum(g[max(0, adim - KADIM + 1):adim + 1]) > KOTA:
        return {"durum": "hiz_siniri", "giris": 0, "cikis": 0, "yanit": ""}
    bel = belirtecle(istem)
    r = uretec((tohum ^ izno(istem)) + 7919 * deneme)
    if r() < 0.03 + 0.0006 * len(bel):                  # cikti baslamadan kesildi
        return {"durum": "zaman_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    k = etiketle(bel)
    if r() < 0.09:                                      # yarida kesilen cikti
        return {"durum": "yarim_cikti", "giris": len(bel), "cikis": 1, "yanit": k[:2]}
    return {"durum": "tamam", "giris": len(bel), "cikis": len(belirtecle(k)),
            "yanit": k}


SUNUCU["gecmis"] = []
print("tek cagri :", cagir(istemi(TALEP[0]), 0))
SUNUCU["gecmis"] = [KOTA]                               # pencere doldurulmus durumda
print("dolu pencere :", cagir(istemi(TALEP[1]), 0))
SUNUCU["gecmis"] = []
sinif = {}
for t in TALEP:
    SUNUCU["gecmis"] = []
    y = cagir(istemi(t), 0)
    a, b = sinif.get(y["durum"], (0, 0))
    sinif[y["durum"]] = (a + 1, b + y["giris"] + y["cikis"])
print("\nsinif        adet  belirtec  sonuc")
for d in ("tamam", "zaman_asimi", "yarim_cikti"):
    a, b = sinif[d]
    print(f"{d:<12} {a:>4}  {b:>8}  {'kullanilir' if d == 'tamam' else 'atilir'}")
```

```
tek cagri : {'durum': 'tamam', 'giris': 44, 'cikis': 2, 'yanit': 'kesinti'}
dolu pencere : {'durum': 'hiz_siniri', 'giris': 0, 'cikis': 0, 'yanit': ''}

sinif        adet  belirtec  sonuc
tamam         137      6523  kullanilir
zaman_asimi     9       436  atilir
yarim_cikti    14       655  atilir
```

Son tabloda pencere her çağrıdan önce boşaltıldı, yani hız sınırı devre dışı ve geriye yalnız
içerik başarısızlıkları kaldı. Yirmi üç istek düşüyor ve bu isteklerin **1091 belirteci ödenmiş,
karşılığı alınmamıştır**. Toplamın 7614 belirteç olduğu düşünülürse boşa giden pay **0,1433**.
Bu, hiçbir yeniden deneme yapılmadan, tek denemeli bir istemcide ödenen bedeldir.

İki başarısızlık sınıfının bedeli eşit değildir. Zaman aşımı dokuz istekte 436 belirteç yakıyor;
yarım çıktı on dört istekte 655. Reddedilen çağrı ise sıfır belirteç harcıyor — ödeme açısından
en ucuz başarısızlık odur. Bu sıralama, yeniden deneme politikasının niçin körlemesine
kurulamayacağını söylüyor: reddedilmiş bir çağrıyı tekrar göndermek yalnız bir çağrıya mal olur,
yarıda kesilmiş bir çağrıyı tekrar göndermek girişin tamamını ikinci kez ödetir.

## Yük Altında Üç Politika

Şimdi aynı 160 talep bir zaman ekseninde koşturulur. İlk yüz adımda adım başına bir istek gelir;
otuzuncu adımda bir **patlama** başlar ve altmış istek ya üçerli ya altışarlı olarak yığılır.
Aynı hız sınırını, saha uygulamasından iki adımda bir gelen etkileşimli durum sorgusu da kullanır.
Üç politika karşılaştırılır: yeniden deneme yok, **sabit aralıklı** (her başarısızlıktan bir adım
sonra) ve **geri çekilmeli** (bir, iki, dört adım sonra).

```python
def kosum(politika, yuk, tohum=TOHUM):
    """politika: yok | sabit | geri . yuk: patlama sirasinda adim basina istek."""
    SUNUCU["gecmis"] = []
    varis = [[] for _ in range(BUTCE)]
    for i in range(len(TALEP)):
        varis[i if i < 100 else 30 + (i - 100) // yuk].append(i)
    kuyruk, etkin = [], []
    s = dict.fromkeys(("cagri", "hiz", "icerik", "bel", "bos", "tamam", "dogru",
                       "etamam", "etoplam"), 0)
    for adim in range(BUTCE):
        if adim % 2 == 0 and adim < 120:                # etkilesimli akis
            etkin.append({"a": adim, "d": 0})
            s["etoplam"] += 1
        for i in varis[adim]:
            kuyruk.append({"i": i, "hazir": adim, "deneme": 0})
        for x in list(etkin):
            if x["a"] + 1 < adim:                       # gecikme butcesi doldu
                etkin.remove(x)
                continue
            y = cagir(f"Saha uygulamasi sorgusu {x['a']} : acik kayit sayisi",
                      adim, x["d"], tohum)
            s["bel"] += y["giris"] + y["cikis"]
            if y["durum"] == "tamam":
                s["etamam"] += 1
                etkin.remove(x)
            else:
                s["bos"] += y["giris"] + y["cikis"]
                x["d"] += 1
        for x in [x for x in kuyruk if x["hazir"] <= adim][:ESZAMAN]:
            kuyruk.remove(x)
            t = TALEP[x["i"]]
            y = cagir(istemi(t), adim, x["deneme"], tohum)
            s["cagri"] += 1
            s["bel"] += y["giris"] + y["cikis"]
            if y["durum"] == "tamam":
                s["tamam"] += 1
                s["dogru"] += y["yanit"] == t["konu"]
                continue
            s["bos"] += y["giris"] + y["cikis"]
            s["hiz" if y["durum"] == "hiz_siniri" else "icerik"] += 1
            x["deneme"] += 1
            if politika == "yok" or x["deneme"] >= EN_COK:
                continue
            x["hazir"] = adim + (1 if politika == "sabit" else 2 ** (x["deneme"] - 1))
            kuyruk.append(x)
    n = len(TALEP)
    return (s["tamam"] / n, s["etamam"] / s["etoplam"], s["cagri"], s["hiz"],
            s["icerik"], s["bel"], s["bos"], s["dogru"] / n)


print("yuk  politika  tamamlanan  etkilesimli  cagri  hiz reddi  icerik hatasi"
      "  belirtec  bosa giden  isabet")
for yuk, ad in ((3, "hafif"), (6, "agir ")):
    for p in ("yok", "sabit", "geri"):
        a = kosum(p, yuk)
        print(f"{ad}  {p:<8} {a[0]:>10.4f}  {a[1]:>11.4f}  {a[2]:>5}  {a[3]:>9}"
              f"  {a[4]:>13}  {a[5]:>8}  {a[6]:>10}  {a[7]:>6.4f}")
print("\nikinci kosum (tohum 20260219), tamamlanan / etkilesimli:")
for yuk, ad in ((3, "hafif"), (6, "agir ")):
    b = [kosum(p, yuk, TOHUM + 1) for p in ("yok", "sabit", "geri")]
    print(f"  {ad} " + "  ".join(f"{p}: {x[0]:.4f} / {x[1]:.4f}"
                                 for p, x in zip(("yok", "sabit", "geri"), b)))
```

```
yuk  politika  tamamlanan  etkilesimli  cagri  hiz reddi  icerik hatasi  belirtec  bosa giden  isabet
hafif  yok          0.8562       0.9500    160          0             23      8425        1218  0.8438
hafif  sabit        1.0000       0.9500    185          0             25      9634        1311  0.9875
hafif  geri         1.0000       0.9500    185          0             25      9634        1311  0.9875
agir   yok          0.8562       0.9500    160          0             23      8425        1218  0.8438
agir   sabit        0.8000       0.8667    295        151             16      7658         873  0.7937
agir   geri         0.8750       0.8833    289        129             20      8389        1038  0.8625

ikinci kosum (tohum 20260219), tamamlanan / etkilesimli:
  hafif yok: 0.8750 / 1.0000  sabit: 1.0000 / 1.0000  geri: 1.0000 / 1.0000
  agir  yok: 0.8750 / 1.0000  sabit: 0.6813 / 0.8667  geri: 0.7188 / 0.8833
```

Tablonun okunması gereken ilk satırı, düzeneksiz istemcinin **iki yükte de aynı** olmasıdır:
0,8562 tamamlanma, **sıfır hız sınırı reddi**. Patlamanın adım başına üçten altıya çıkması
düzeneksiz istemci için hiçbir şeyi değiştirmiyor, çünkü gelen yük hâlâ sınırın altında kalıyor.
Sınır, iş yükü tarafından değil, **düzenek tarafından** aşılacak.

Hafif yükte yeniden deneme tam olarak beklendiği gibi çalışıyor: tamamlanma 0,8562'den
**1,0000'a** çıkıyor ve iki politika **birbirinin aynısı** — çünkü hiç red olmadığında geri
çekilmenin geciktirecek bir şeyi yoktur. Bedel açık: 25 ek çağrı, 1209 ek belirteç, ve boşa giden
belirteç 1218'den 1311'e. Yani kurtarılan yirmi üç isteğin karşılığında ödenen belirtecin bir
kısmı yine boşa gitti, çünkü kimi yeniden deneme de düştü.

## Yeniden Denemenin Kimin İşini Bozduğu

Ağır yük satırları kursun ikinci iddiasının en açık örneğidir. Sabit aralıklı yeniden deneme
tamamlanmayı **0,8562'den 0,8000'e düşürüyor**. Düzenek eklendi, sayı geriledi. Nedeni sütunlarda
duruyor: çağrı 160'tan 295'e çıkıyor ve bu çağrıların **151'i hız sınırından reddediliyor**.
Reddedilen çağrılar da pencerede sayıldığı için her red bir sonraki reddi kolaylaştırıyor;
düzeltmek için gönderilen çağrı, düzeltilecek sorunu büyütüyor. İçerik hatası 23'ten 16'ya
düşerken toplam tamamlanma da düşüyor: istekler artık içerik yüzünden değil, **kendi
denemelerinin yarattığı tıkanıklık** yüzünden kaybediliyor.

Geri çekilmeli deneme aynı yükte 0,8750 veriyor, yani düzeneksize göre **0,0188** üstünde. Bu
sayının yanına ikinci koşum konmalıdır: düzeneksiz istemci tohum 20260219'da 0,8750 veriyor ve iki
koşum farkı da tam **0,0188**. Kazanç, koşum farkını aşmıyor, dolayısıyla **ölçülmemiş sayılır**.
Buna karşılık sabit aralıklının kaybı 0,0562, yani koşum farkının üç katı — kayıp ölçülmüştür.
İkinci koşumun ağır yük satırları bunu doğruluyor: orada iki politika da düzeneksizin altına
düşüyor (0,6813 ve 0,7188).

Son sütun, çoğu ölçümde hiç bakılmayan yerdedir. Etkileşimli akış aynı hız sınırını paylaşıyor ve
kendi yeniden denemesi yok; gecikme bütçesi bir adım. Düzeneksiz istemcide bu akış 0,9500
tamamlıyor. Toplu işe yeniden deneme eklendiğinde **0,8667'ye** düşüyor. Etkileşimli akış hiçbir
şey değiştirmedi, isteği artmadı, istemi büyümedi; yalnız **komşusu dayanıklı hâle geldi**.
Bu, dayanıklılık düzeneğinin en sinsi bedelidir: kendi ölçütünü kurtarırken paylaşılan bir kaynağı
tüketir ve zararı **başka bir ölçütte** görünür. Bir yeniden deneme politikası yalnız kendi
başarısızlık payıyla değerlendirilirse bu satır hiç görülmez.

## Özet

- Bir çağrının üç başarısızlığı ayrı bedeller taşır: hız sınırı reddi belirteç harcamaz, zaman
  aşımı girişi öder, yarım çıktı giriş ile kısmi çıkışı öder; tek denemeli istemcide boşa giden
  belirteç payı 0,1433'tür.
- Düzeneksiz istemci hafif ve ağır yükte aynı sonucu veriyor (0,8562) ve hiç hız sınırına
  takılmıyor; sınırı iş yükü değil, eklenen düzenek aşıyor.
- Hafif yükte yeniden deneme tamamlanmayı 1,0000'a çıkarıyor ve sabit aralıklı ile geri çekilmeli
  arasında fark yok; bedel 25 ek çağrı ve 1209 belirteçtir.
- Ağır yükte sabit aralıklı deneme tamamlanmayı 0,8000'e düşürüyor ve 151 hız sınırı reddi
  üretiyor: düzeltmek için gönderilen çağrı, düzeltilecek sorunu büyütüyor.
- Geri çekilmeli denemenin ağır yükteki kazancı 0,0188, iki koşum farkı da 0,0188; kazanç
  ölçülmemiş sayılır, buna karşılık sabit aralıklının 0,0562'lik kaybı ölçülmüştür.
- Aynı sınırı paylaşan etkileşimli akış 0,9500'den 0,8667'ye iniyor; dayanıklılık düzeneği kendi
  ölçütünü kurtarırken zararı başka bir ölçütte bırakıyor.

## Sonraki Adım

Bu derste her çağrı sıfırdan gönderildi. Oysa tabloya giren 160 istemin hepsi aynı yönergeyle
başlıyor ve o yönerge her seferinde yeniden belirteçleniyor, yeniden ödeniyor. Yeniden deneme bu
tekrarı bir kat daha büyütüyor: ağır yükte 295 çağrının hepsi aynı ortak metni taşıyor. Tekrarın
kendisi bir bedeldir ve bu bedel, yanıtın veya ortak bağlamın saklanmasıyla düşürülebilir.
Ama saklanan bir yanıtın bir yaşı vardır: dayandığı belge değişmişse yanıt hâlâ hızlıdır, hâlâ
ucuzdur ve artık yanlıştır. Sonraki ders iki sayıyı yan yana koyar: önbellek isabeti yükseldikçe
belirteç ne kadar düşüyor ve **bayat yanıt payı** ne kadar büyüyor.
