---
title: 'Zaman Aşımı ve Yeniden Deneme Bütçesi'
source: 'https://academia.sh/tr/kurslar/uygulama-katmani/zaman-asimi-ve-yeniden-deneme-butcesi'
course: 'Uygulama Katmanı ve Servis Etkileşimi'
language: tr
updated: '2026-08-17T18:10:55+00:00'
license: 'CC BY-SA 4.0'
---

# Zaman Aşımı ve Yeniden Deneme Bütçesi

Uçtan uca gecikme eşiğinin zincirdeki adımlara bölüştürülmesi: zaman aşımı ile deneme sayısının çarpımının en kötü durumda bütçeyi kaç katına çıkardığının hesaplanması, son tarih aktarımının eşik aşımını erken başarısızlığa çevirmesi, kısa zaman aşımının geçici yavaşlığı soğurması ve deneme bütçesi konmadığında yaygın yavaşlamada iç istek hızının kaça katlandığının modelle ölçülmesi.

Dört ders sonunda çağrı yapılabilir durumda: servisler durumsuz, adresleri çalışma zamanında
bulunuyor, konuşma biçimi seçilmiş ve sözleşmeleri kırılmadan evrilebiliyor. Bir soru hâlâ açık ve
o soru bu konunun ilk ölçüsüne geri döner. Ağ geçidi iki servisi çağırdığında birinden yanıt
gelmezse ne kadar bekleyecek, kaç kez deneyecek ve bu bekleme uçtan uca yanıta ne ekleyecek.

Yeniden deneme kararı, üstel geri çekilme, sarsıntı ve devre kesici Uygulama Mimarisi kursunda
kuruldu; algoritmalar burada yeniden anlatılmaz. Bu dersin ele aldığı şey bir **bütçedir**.
Bütçenin kaynağı K01'dir: takip okumasının sıkı eşiği **200 milisaniye** ve o eşiğin kaynağı
alıcının takip sayfasından beklediği yanıt süresidir. Zincirdeki adım sayısı da ölçülmüştü —
üçüncü ders bir dış istek için iki iç çağrı saydı ve bunun protokolden değil alan bölünmesinden
geldiğini gösterdi.

## Bütçenin Bölüştürülmesi

Zincir şudur: ağ geçidi iki servisi paralel çağırır, her servis kendi deposunu çağırır. Derinlik
2, kol 2, toplam dört adım çağrısı. Ağ geçidinin kendi işi de bir pay ister; bu **bu kursun
varsayımıdır**.

**U3 — ağ geçidinin kendi payı 20 ms.** Gerekçe: doğrulama, kapı denetimleri ve iki yanıtın
birleştirilmesi K02'de kenara taşınmıştı ve bu işler bütçeden yer tutar. Duyarlılığı aşağıda
hesaplandı; K01'in tablosuna eklenmez.

```js
// zincir/butce.mjs — uctan uca butcenin zincire bolusturulmesi; belirlenimli aritmetik
const UCTAN_UCA = 200;      // K01 Islevsel Olmayan Gereksinimler: okuma esigi (siki) 200 ms
const GECIT_PAYI = 20;      // varsayim U3: ag gecidinin kendi isine ayirdigi pay (ms)
const ADIM_ORTANCA = 8;     // model parametresi: bir adim cagrisinin olagan suresi (ms)
const kalan = UCTAN_UCA - GECIT_PAYI;

console.log(`uctan uca ${UCTAN_UCA} ms, gecidin payi ${GECIT_PAYI} ms, adimlara kalan ${kalan} ms\n`);
console.log(`${"derinlik".padStart(9)}${"deneme".padStart(8)}${"butcesiz en kotu(ms)".padStart(22)}` +
  `${"butceye oran".padStart(14)}${"bolusturulmus zaman asimi(ms)".padStart(31)}${"ortancaya oran".padStart(16)}`);
for (const k of [1, 2, 3, 4]) {
  for (const d of [1, 3]) {
    const butcesiz = k * d * UCTAN_UCA + GECIT_PAYI;
    const t = kalan / (k * d);
    console.log(`${String(k).padStart(9)}${String(d).padStart(8)}${String(butcesiz).padStart(22)}` +
      `${`x${(butcesiz / UCTAN_UCA).toFixed(1)}`.padStart(14)}${t.toFixed(1).padStart(31)}` +
      `${`x${(t / ADIM_ORTANCA).toFixed(2)}`.padStart(16)}`);
  }
}
const enDerin = Math.floor(kalan / (3 * ADIM_ORTANCA));
console.log(`\ndeneme 3 ve adim ortancasi ${ADIM_ORTANCA} ms iken zaman asimi ortancanin altina ` +
  `dusmeden en cok ${enDerin} adim derinlige inilebilir`);
console.log(`duyarlilik: gecit payi ${GECIT_PAYI} -> ${GECIT_PAYI * 2} ms olsaydi derinlik 2, deneme 3 icin ` +
  `zaman asimi ${(kalan / 6).toFixed(1)} -> ${((UCTAN_UCA - 2 * GECIT_PAYI) / 6).toFixed(1)} ms`);
```

```
uctan uca 200 ms, gecidin payi 20 ms, adimlara kalan 180 ms

 derinlik  deneme  butcesiz en kotu(ms)  butceye oran  bolusturulmus zaman asimi(ms)  ortancaya oran
        1       1                   220          x1.1                          180.0          x22.50
        1       3                   620          x3.1                           60.0           x7.50
        2       1                   420          x2.1                           90.0          x11.25
        2       3                  1220          x6.1                           30.0           x3.75
        3       1                   620          x3.1                           60.0           x7.50
        3       3                  1820          x9.1                           20.0           x2.50
        4       1                   820          x4.1                           45.0           x5.63
        4       3                  2420         x12.1                           15.0           x1.88

deneme 3 ve adim ortancasi 8 ms iken zaman asimi ortancanin altina dusmeden en cok 7 adim derinlige inilebilir
duyarlilik: gecit payi 20 -> 40 ms olsaydi derinlik 2, deneme 3 icin zaman asimi 30.0 -> 26.7 ms
```

Bu sayılar **hesap** sınıfındadır. Üçüncü kolon en sık yapılan hatayı gösteriyor: her adıma
uçtan uca eşiğin kendisi zaman aşımı olarak verilirse, derinlik 2 ve deneme 3'te en kötü süre 1220
milisaniyedir — bütçenin 6,1 katı. Zaman aşımını eşiğe eşitlemek bütçeyi korumaz; **her adım tek
başına bütçenin tamamını harcayabilir hâle gelir.**

Beşinci kolon doğru bölüştürmeyi veriyor ve bir sınır getiriyor. Adıma düşen zaman aşımı, derinlik
ve deneme sayısının çarpımına bölünür: derinlik 2 ve deneme 3'te 30 milisaniye, derinlik 4'te 15
milisaniye. Son kolon bunun neden bir sınır olduğunu söylüyor — zaman aşımı adımın olağan süresine
yaklaştıkça olağan istekler de zaman aşımına uğramaya başlar. Sekiz milisaniyelik bir adım
ortancasında ve üç denemede bütçe en çok yedi adım derinliğe dayanır.

Bu, servis bölünmesi ile gecikme eşiği arasındaki bağdır: **zincire eklenen her adım bütçeyi
böler, sonsuza kadar bölünemez.**

## Model

Aşağıdaki koşum bir **modeldir**: mantıksal saat kullanır, adım süreleri bir döngüden okunur ve
yavaşlama parametreyle tetiklenir. İki rejimde çalışır — olağan rejimde adımların çoğu hızlıdır ve
arada bir yanıt vermeyen bir adım geçer; yaygın yavaşlama rejiminde adımların çoğu yanıt vermez.
Gerçek bir servis kümesi ya da ağ kurulmaz.

```js
// zincir/kosum.mjs — zincirin MODELI: mantiksal saat, adim sureleri parametre, iki rejim.
// Zincir: ag gecidi -> (teslimat-op, ucretlendirme) paralel -> her biri kendi deposu. Derinlik 2, kol 2.
const N = 40, ESIK = 200, GECIT_PAYI = 20, DERINLIK = 2, KOL = 2, ADIM = DERINLIK * KOL;
const REJIM = {                                   // model parametresi: adim cagrisinin suresi (ms)
  olagan: [6, 7, 6, 8, 6, 7, 6, 45, 6, 7, 6, 8, 6, 7, 6, 1000],
  "yaygin yavaslama": [6, 1000, 1000, 1000, 6, 1000, 1000, 1000],
};

function kosum({ zamanAsimi, deneme, sonTarih, denemeButcesi }, rejim) {
  let s = 0, birincil = 0, ek = 0;
  const sayim = { yanit: 0, esikDisi: 0, dusen: 0 }, uctanUca = [];
  const sure = () => REJIM[rejim][s++ % REJIM[rejim].length];
  const izin = () => denemeButcesi === null || ek < denemeButcesi * birincil;

  const adim = (kalan) => {                       // tek adim: zaman asimi ve yeniden deneme
    let gecen = 0;
    for (let i = 0; i < deneme; i += 1) {
      const zt = sonTarih ? Math.min(zamanAsimi, kalan - gecen) : zamanAsimi;
      if (zt <= 0) return { ok: false, gecen };
      if (i === 0) birincil += 1; else ek += 1;
      const su = sure();
      if (su <= zt) return { ok: true, gecen: gecen + su };
      gecen += zt;
      if (i + 1 < deneme && izin() === false) return { ok: false, gecen };
    }
    return { ok: false, gecen };
  };
  const kol = () => {                             // bir kol: DERINLIK adet ardisik adim
    let gecen = 0, ok = true;
    for (let d = 0; d < DERINLIK && ok; d += 1) {
      const r = adim(ESIK - GECIT_PAYI - gecen);
      gecen += r.gecen; ok = r.ok;
    }
    return { ok, gecen };
  };

  for (let i = 0; i < N; i += 1) {
    const kollar = Array.from({ length: KOL }, kol);   // paralel: sure kollarin en buyugudur
    const gecen = GECIT_PAYI + Math.max(...kollar.map((k) => k.gecen));
    uctanUca.push(gecen);
    if (kollar.every((k) => k.ok) === false) sayim.dusen += 1;
    else if (gecen > ESIK) sayim.esikDisi += 1;
    else sayim.yanit += 1;
  }
  const sirali = [...uctanUca].sort((a, b) => a - b);
  return { ...sayim, ortanca: sirali[N >> 1], enKotu: sirali[N - 1],
    carpan: (birincil + ek) / (N * ADIM) };
}

const YAPILANDIRMA = [
  ["butce yok (200/3)", { zamanAsimi: 200, deneme: 3, sonTarih: false, denemeButcesi: null }],
  ["+ son tarih aktarimi", { zamanAsimi: 200, deneme: 3, sonTarih: true, denemeButcesi: null }],
  ["+ bolusturulmus (30/3)", { zamanAsimi: 30, deneme: 3, sonTarih: true, denemeButcesi: null }],
  ["+ deneme butcesi 0.30", { zamanAsimi: 30, deneme: 3, sonTarih: true, denemeButcesi: 0.3 }],
];
const OKUMA_TEPE = 416.67, IC_TABAN = OKUMA_TEPE * ADIM;   // K01: tepe okuma; 03. ders: adim sayisi

console.log(`${N} dis istek, derinlik ${DERINLIK}, kol ${KOL}, adim ${ADIM}; ` +
  `uctan uca esik ${ESIK} ms (K01), gecit payi ${GECIT_PAYI} ms (U3)`);
console.log(`ic istek/s tabani = ${OKUMA_TEPE} x ${ADIM} = ${IC_TABAN.toFixed(2)}`);
for (const rejim of Object.keys(REJIM)) {
  console.log(`\n-- ${rejim}: ${REJIM[rejim].filter((v, i, a) => a.indexOf(v) === i).join("/")} ms dongusu --`);
  console.log(`${"yapilandirma".padEnd(24)}${"esik ici".padStart(9)}${"esik disi".padStart(10)}` +
    `${"dusen".padStart(7)}${"ortanca".padStart(9)}${"en kotu".padStart(9)}${"carpan".padStart(8)}` +
    `${"ic istek/s".padStart(12)}`);
  for (const [ad, y] of YAPILANDIRMA) {
    const r = kosum(y, rejim);
    console.log(`${ad.padEnd(24)}${String(r.yanit).padStart(9)}${String(r.esikDisi).padStart(10)}` +
      `${String(r.dusen).padStart(7)}${String(r.ortanca).padStart(9)}${String(r.enKotu).padStart(9)}` +
      `${`x${r.carpan.toFixed(2)}`.padStart(8)}${(IC_TABAN * r.carpan).toFixed(2).padStart(12)}`);
  }
}
console.log(`\nsinirsiz denemenin ust siniri: her adim 3 deneme -> ${(IC_TABAN * 3).toFixed(2)} istek/s`);
```

```
40 dis istek, derinlik 2, kol 2, adim 4; uctan uca esik 200 ms (K01), gecit payi 20 ms (U3)
ic istek/s tabani = 416.67 x 4 = 1666.68

-- olagan: 6/7/8/45/1000 ms dongusu --
yapilandirma             esik ici esik disi  dusen  ortanca  en kotu  carpan  ic istek/s
butce yok (200/3)              30        10      0       71      233   x1.06     1770.85
+ son tarih aktarimi           30         0     10       71      200   x1.00     1666.68
+ bolusturulmus (30/3)         40         0      0       62       63   x1.14     1895.85
+ deneme butcesi 0.30          40         0      0       62       63   x1.14     1895.85

-- yaygin yavaslama: 6/1000 ms dongusu --
yapilandirma             esik ici esik disi  dusen  ortanca  en kotu  carpan  ic istek/s
butce yok (200/3)               0         0     40      626      626   x2.00     3333.36
+ son tarih aktarimi            0         0     40      200      200   x0.67     1114.59
+ bolusturulmus (30/3)          0         0     40      116      116   x2.00     3333.36
+ deneme butcesi 0.30           0         0     40       86       86   x0.97     1614.60

sinirsiz denemenin ust siniri: her adim 3 deneme -> 5000.04 istek/s
```

## Dört Satırın Okunması

**Son tarih aktarımı eşik aşımını erken başarısızlığa çevirir.** Olağan rejimde bütçesiz düzen
kırk isteğin otuzunu eşik içinde yanıtlıyor, onunu eşiğin dışında — en kötü 233 milisaniye.
Çağıran kalan bütçeyi çağrıyla birlikte geçirdiğinde en kötü süre tam 200 milisaniyede kesiliyor
ve o on istek eşik dışı olmaktan çıkıp düşen istek oluyor. Değiş tokuş açıktır: geç bir yanıt ile
zamanında bir başarısızlık arasında seçim yapılıyor. Kullanıcının 233 milisaniyede aldığı yanıt
zaten eşiği karşılamıyordu; onu üretmek için harcanan iş de karşılıksızdı.

**Kısa zaman aşımı geçici yavaşlığı soğuruyor.** Bölüştürülmüş düzende zaman aşımı 30
milisaniyeye indiğinde kırk isteğin kırkı eşik içinde yanıtlanıyor ve en kötü süre 63 milisaniye
oluyor. Nedeni modelin varsayımıdır: yavaşlık geçicidir, aynı adımın ikinci çağrısı hızlı döner.
Uzun zaman aşımı bu geçici yavaşlığı bekleyerek uçtan uca yanıta taşıyor, kısa zaman aşımı ise onu
kesip yeniden deniyor. Karşılığı çağrı çarpanının 1,00'den 1,14'e çıkması: iç istek hızı 1666,68'den
1895,85 istek/s'ye yükseliyor.

**Deneme bütçesi olağan rejimde bağlamıyor.** Dördüncü satır üçüncüyle aynı. Gözlenen çarpan 1,14
ve bütçe 1,30 olduğu için sınır hiç devreye girmiyor. Bir bütçenin olağan koşulda görünmez olması
doğru boyutlandırıldığının işaretidir.

## Yaygın Yavaşlamada Ne Değişiyor

İkinci tablo aynı yapılandırmaları adımların çoğunun yanıt vermediği bir rejimde koşturuyor ve
sıralama tersine dönüyor.

Bütçesiz düzende kırk isteğin kırkı düşüyor ve çağıran bunu öğrenmek için 626 milisaniye
bekliyor. Son tarih aktarımı bu süreyi 200 milisaniyede kesiyor; çarpan 0,67'ye iniyor, çünkü
bütçe tükendiğinde yapılmayan birincil çağrılar da var. İç istek hızı 3333,36'dan 1114,59
istek/s'ye düşüyor.

Üçüncü satır dersin en önemli sayısıdır. Zaman aşımı 30 milisaniyeye indirildiğinde uçtan uca
süre 116 milisaniyeye iniyor — ama çarpan yeniden 2,00'ye çıkıyor ve iç istek hızı 3333,36 istek/s
oluyor. Kısa zaman aşımı, aynı bütçeye daha çok deneme sığdırır; **zaten yavaşlamış olan servis,
kendisini yavaşlatan sistemden iki kat istek alır.** Olağan rejimde iyi olan karar, arıza
rejiminde zararlıdır.

Dördüncü satır bunu kesiyor. Deneme bütçesi ek denemeleri birincil çağrıların yüzde otuzuyla
sınırladığında çarpan 0,97'ye, iç istek hızı 1614,60 istek/s'ye iniyor: iki kat yükseltme yerine
taban hızın altında bir yük. Uçtan uca süre de 116'dan 86 milisaniyeye iniyor, çünkü boşa giden
denemeler yapılmıyor. Sınırsız denemenin üst sınırı karşılaştırma noktasıdır — her adım üç kez
denenirse 5000,04 istek/s, K01'in uçtaki tepe hızının neredeyse on katı bir iç yük.

Bütün bunlar yalnız yeniden denenebilir çağrılar için geçerlidir. Durum değiştiren bir çağrının
yeniden denenebilmesi, aynı çağrının iki kez işlenmesinin tek kez işlenmesiyle aynı sonucu
vermesine bağlıdır; bu özelliğe **etkisiz** (idempotent) denir ve HTTP yöntemlerinin etkisizlik
özelliğiyle aynı kavramdır. Etkisiz olmayan bir çağrı ancak istemcinin ürettiği bir **tekillik
anahtarı** sözleşmeye yazılmışsa yeniden denenebilir; ikisi de Web API Tasarımı kursunda kuruldu.

## Özet

- Uçtan uca eşik bir bütçedir ve zincire bölüştürülür; her adıma eşiğin tamamı zaman aşımı olarak
  verilirse derinlik 2 ve deneme 3'te en kötü süre bütçenin 6,1 katına çıkar.
- Bölüştürülmüş zaman aşımı derinlik ile deneme sayısının çarpımına bölünür (derinlik 2, deneme
  3'te 30 ms) ve adımın olağan süresine yaklaştığında sınıra dayanır: 8 ms ortanca ve 3 denemeyle
  bütçe en çok 7 adım derinliğe dayanır.
- Son tarih aktarımı en kötü süreyi eşikte kesiyor: olağan rejimde 233 ms ve 10 eşik dışı yanıt,
  200 ms ve 10 düşen isteğe dönüşüyor — geç yanıt yerine zamanında başarısızlık.
- Kısa zaman aşımı geçici yavaşlığı soğuruyor (40/40 eşik içi, en kötü 63 ms) ve bedeli çağrı
  çarpanının 1,00'den 1,14'e, iç istek hızının 1666,68'den 1895,85 istek/s'ye çıkmasıdır.
- Yaygın yavaşlamada aynı karar tersine dönüyor: kısa zaman aşımı çarpanı 2,00'ye ve iç istek
  hızını 3333,36 istek/s'ye çıkarıyor; deneme bütçesi 0,30 bunu 0,97 ve 1614,60 istek/s'ye
  indiriyor ve uçtan uca süreyi 116'dan 86 ms'ye düşürüyor.
- Yeniden deneme yalnız etkisiz çağrılar için serbesttir; etkisiz olmayan bir çağrı ancak
  sözleşmede bir tekillik anahtarı varsa denenebilir.

## Sonraki Adım

Bu konu **eşzamanlı** çağrıyı tasarladı: çağıran bekler, bütçe işler, sonunda ya yanıt gelir ya
hata. Bütçe hesabı bir sınırı görünür kıldı — zincir uzadıkça ya bütçe parçalara bölünüp her adım
daralır ya da uçtan uca süre büyür. İki seçenek de aynı varsayımın içindedir: çağıran işin
sonucunu bekliyor. Bazı işler için üçüncü bir yol vardır ve o yol varsayımı kaldırır — çağıran hiç
beklemez. Taşıyıcıdan gelen durum olayının deponun içine yazılması, isteği yanıtlamak için
tamamlanmak zorunda değildir. Sonraki konu isteği bir kuyruğa bırakmanın ne değiştirdiğini ölçer
ve bunu bir kapasite sorusu olarak sorar: eşzamanlı yolda kapasite anlık tepeye göre seçilmek
zorundadır, kuyruk konduğunda ortalamaya yaklaştırılabilir; kazancın bekleyen iş ve bekleme süresi
cinsinden ne ödettiği ve K01'in hangi sayısının değiştiği orada hesaplanır.
