---
title: 'Önbellek Sunucusu'
source: 'https://academia.sh/tr/kurslar/sunucu-ve-sertlestirme/onbellek-sunucusu'
course: 'Sunucu, Ağ ve Sertleştirme'
language: tr
updated: '2026-08-17T18:09:10+00:00'
license: 'CC BY-SA 4.0'
---

# Önbellek Sunucusu

İki katmanlı önbellekte isabetin kenar ile kaynak arasında nasıl bölündüğü: kenarı üç düğüme bölmenin uygulamaya inen isteği elliden yüz kırk üçe çıkarması ve kaynak önbelleğinin onu ona indirmesi, geçersizleştirmenin yayılma penceresinin üç yüz altmış saniyeden on bir saniyeye inmesi, tazelik ayarının bu pencereye etkisi ve kişiye özel yanıtın paylaşılan önbelleğe düşmesiyle açılan paylaşılan anahtar yüzeyi.

Son üç ders isteğin yolunu kurdu ve şifreledi: kim geldiği aktarıldı, şifre bir yerde sonlandı,
sertifika kendi kendine tazeleniyor. Yolun tamamı her istek için baştan sona koşuyor.

Ölçüm ağının panosu her açılışta aynı bölge haritasını, aynı sayaç listesini ve aynı gecelik
özet dosyasını istiyor. Bu isteklerin çoğu aynı yanıtı üretiyor. Yanıt bir yerde tutulabilir —
ama "bir yer" iki ayrı yerdir. **Kenar önbelleği** istemciye yakın durur ve isteği ağın uzağına
hiç göndermez. **Kaynak önbelleği** uygulamanın önünde durur ve uygulamanın aynı yanıtı iki kez
üretmesini engeller.

Önbelleğin ne olduğu, isabet oranının nasıl hesaplandığı ve tazeliğin ne anlama geldiği daha
önce ölçülmüştü; bu ders o mekaniği tekrarlamaz. Burada ölçülen üç şeydir: iki katman arasında
isabetin nasıl **bölündüğü**, bir içerik değiştiğinde eskisinin kenarda kaç saniye daha durduğu
ve yanlış bir önbellek anahtarının açtığı yüzey.

- **WS25.** İstek akışı kendi üretecimizle üretilir; tohum `20260` görünürdür ve koşumdan
  koşuma aynı diziyi verir. İki bin istek, altı yüz saniyeye yayılır.
- **WS26.** Beş içerik vardır ve ağırlıkları sabittir; biri (`/fatura/ozet`) kişiye özeldir,
  yani yanıtı isteği yapan aboneye göre değişir.
- **WS27.** Bir abone hep aynı kenar düğümüne düşer: düğüm, abone kimliğinin düğüm sayısına
  bölümünden kalandır.
- **WS28.** Varsayılan önbellek anahtarı **yalnız yoldur**; kimlik anahtara girmez. İki seçenek
  daha ölçülür: anahtara kimliği eklemek ve kişiye özel içeriği hiç saklamamak.
- **WS29.** Geçersizleştirme yayınının üç kenar düğümüne ulaşma süresi kurgudur: iki, beş ve on
  bir saniye. Pencere en yavaş düğüme göre hesaplanır.
- **WS30.** Model süre ölçmez; saniye değerleri tazelik ayarlarından ve kurgu gecikmelerden
  türer, eski yanıt alan istek sayısı değişen içeriğin trafik payından hesaplanır.

```js
// onbellek/katman.mjs — model: iki katmanli onbellek (kenar + kaynak). Kurgu olcum aginin
// istek akisi kendi uretecimizle uretilir; tohum gorunur. Onbellek mekanigi yeniden
// tanimlanmaz, iki katman arasindaki isabet dagilimi ve gecersizlestirme penceresi olculur.
const DONEM = 600, ISTEK = 2000, ABONE = 6, TOHUM = 20260;
// [yol, agirlik, tur]
const ICERIK = [
  ["/bolge/harita", 40, "paylasik"], ["/sayac/liste", 25, "paylasik"],
  ["/gecelik/ozet", 15, "paylasik"], ["/varlik/logo", 10, "paylasik"],
  ["/fatura/ozet", 10, "kisiye-ozel"],
];
const TOPLAM = ICERIK.reduce((a, x) => a + x[1], 0);
const uretec = (tohum) => { let s = tohum >>> 0; return () => (s = (Math.imul(s, 1664525) + 1013904223) >>> 0) / 4294967296; };
const sec = (u) => { let e = u * TOPLAM; return ICERIK.find((x) => (e -= x[1]) < 0) ?? ICERIK[0]; };

function simule({ dugum, kaynakVar, kenarTazelik, kaynakTazelik, anahtar }) {
  const r = uretec(TOHUM);
  const kenar = Array.from({ length: dugum }, () => new Map());
  const kaynak = new Map();
  const s = { kenarIsabet: 0, kaynakIsabet: 0, uygulama: 0, sizanIstek: 0 };
  const sizanAbone = new Set();
  for (let i = 0; i < ISTEK; i += 1) {
    const t = Math.floor((i * DONEM) / ISTEK);
    const [yol, , tur] = sec(r());
    const abone = Math.floor(r() * ABONE);
    const ozel = tur === "kisiye-ozel";
    if (ozel && anahtar === "ozel-gecer") { s.uygulama += 1; continue; }   // ozel icerik hic saklanmaz
    const a = anahtar === "yol+kimlik" && ozel ? `${yol}#${abone}` : yol;
    const k = kenar[abone % dugum];
    const kayitla = (giris) => {                        // isabette kimin yaniti dondu
      if (ozel && giris.abone !== abone) { s.sizanIstek += 1; sizanAbone.add(giris.abone); }
    };
    const ke = k.get(a);
    if (ke && t - ke.t < kenarTazelik) { s.kenarIsabet += 1; kayitla(ke); continue; }
    const kk = kaynakVar ? kaynak.get(a) : undefined;
    if (kk && t - kk.t < kaynakTazelik) {
      s.kaynakIsabet += 1; kayitla(kk); k.set(a, { t, abone: kk.abone }); continue;
    }
    s.uygulama += 1;                                    // iki katman da isabetsiz: uygulama uretir
    if (kaynakVar) kaynak.set(a, { t, abone });
    k.set(a, { t, abone });
  }
  return { ...s, sizanAbone: sizanAbone.size };
}

const E = [8, 9, 14, 15, 16, 18, 14, 13];
const yaz = (h) => h.map((d, i) => String(d)[i ? "padStart" : "padEnd"](E[i])).join("");
console.log(yaz(["dugum", "kaynak", "anahtar", "kenar isabet", "kaynak isabet", "uygulamaya inen",
  "sizan istek", "sizan abone"]));
const AYAR = [
  [1, false, "yol"], [3, false, "yol"], [3, true, "yol"],
  [3, true, "yol+kimlik"], [3, true, "ozel-gecer"],
];
for (const [dugum, kaynakVar, anahtar] of AYAR) {
  const o = simule({ dugum, kaynakVar, kenarTazelik: 60, kaynakTazelik: 300, anahtar });
  console.log(yaz([dugum, kaynakVar ? "var" : "yok", anahtar, o.kenarIsabet, o.kaynakIsabet,
    o.uygulama, o.sizanIstek, o.sizanAbone]));
}

// --- Gecersizlestirmenin yayilma penceresi -------------------------------------
// Icerik kaynakta t=0'da degisti. Pencere, kenarda kac saniye eski icerik kaldigidir.
// Yayin gecikmesi kurgudur: uc kenar dugumune sirasiyla su saniyelerde ulasir.
const GECIKME = [2, 5, 11];
const DEGISEN = ICERIK[0];                              // degisen icerik: /bolge/harita
const HIZ = (ISTEK / DONEM) * (DEGISEN[1] / TOPLAM);    // o icerige gelen istek/saniye
function pencere(yontem, kenarTazelik, kaynakTazelik) {
  if (yontem === "yok") return kenarTazelik + kaynakTazelik;      // iki tazelik ust uste biner
  if (yontem === "kaynakta") return kenarTazelik;                 // kenar kendi suresini bekler
  if (yontem === "her katmanda") return Math.max(...GECIKME);
  return kenarTazelik;                                            // bir dugum yayini kacirdi
}
const P = [22, 16, 17, 20, 22];
const yaz2 = (h) => h.map((d, i) => String(d)[i ? "padStart" : "padEnd"](P[i])).join("");
console.log("\n" + yaz2(["gecersizlestirme", "kenar tazelik", "kaynak tazelik", "pencere(saniye)",
  "eski yanit alan istek"]));
for (const [y, kt, kk] of [["yok", 60, 300], ["yok", 10, 60], ["kaynakta", 60, 300],
  ["kaynakta", 10, 300], ["her katmanda", 60, 300], ["bir dugum kacirdi", 60, 300]]) {
  const p = pencere(y, kt, kk);
  console.log(yaz2([y, kt, kk, p, Math.round(p * HIZ)]));
}
```

```
dugum      kaynak       anahtar   kenar isabet   kaynak isabet   uygulamaya inen   sizan istek  sizan abone
1             yok           yol           1950               0                50           169            5
3             yok           yol           1857               0               143            95            6
3             var           yol           1857             133                10           179            2
3             var    yol+kimlik           1837             143                20             0            0
3             var    ozel-gecer           1664             107               229             0            0

gecersizlestirme         kenar tazelik   kaynak tazelik     pencere(saniye) eski yanit alan istek
yok                                 60              300                 360                   480
yok                                 10               60                  70                    93
kaynakta                            60              300                  60                    80
kaynakta                            10              300                  10                    13
her katmanda                        60              300                  11                    15
bir dugum kacirdi                   60              300                  60                    80
```

## Kenarı Bölmenin Bedeli

İlk iki satır aynı iki bin isteği aynı tazelik ayarlarıyla geçiriyor. Değişen tek şey kenar
düğümü sayısı.

Tek düğümde kenar isabeti bin dokuz yüz elli, uygulamaya inen istek elli. Kenar üç düğüme
bölündüğünde isabet bin sekiz yüz elli yediye iniyor ve uygulamaya inen istek **elliden yüz
kırk üçe** çıkıyor. Yaklaşık üç katı.

Nedeni doğrudan: her düğümün kendi önbelleği vardır ve aynı içeriği üç kez ayrı ayrı ister.
Bir içerik yenilendiğinde artık bir istek değil, üç istek uygulamaya iner. Kenar düğümü sayısı
bir ölçek kararıdır — daha çok düğüm, istemciye daha yakın yanıt demektir — ve uygulamaya inen
yükü **düğüm sayısı kadar çarpar**.

Bu, iki katmanlı önbelleğin varlık nedenidir. Üçüncü satır kaynak önbelleğini ekliyor: kenar
isabeti değişmiyor (bin sekiz yüz elli yedi), yüz otuz üç istek kaynak önbelleğinde karşılanıyor
ve uygulamaya inen istek **ona** düşüyor. Üç düğümün çoğalttığı isteğin neredeyse tamamını
kaynak önbelleği soğuruyor.

Sayılar birlikte okunduğunda kaynak önbelleğinin işi görünür oluyor: kenardan gelen isteğin
kendisini azaltmıyor, o isteğin **uygulamaya varmasını** engelliyor. Üçüncü satırın uygulama
yükü tek düğümlü birinci satırdan da düşüktür — kaynak önbelleği yalnız düğüm çoğalmasını değil,
tek düğümün kendi tazelik dolumlarını da soğuruyor.

## Yayılma Penceresi

İkinci tablo başka bir soruyu ölçüyor. Bölge haritası değişti; yeni harita ne zaman görünür
olur?

Birinci satır varsayılan durumdur: geçersizleştirme yok, iki katman da kendi tazelik süresini
bekliyor. Pencere altmış artı üç yüz, yani **üç yüz altmış saniye**. İki tazeliğin toplanmasının
nedeni üst üste binmedir: kenar, kaynaktan bir kopya çektiğinde o kopya kaynakta üç yüz saniyeye
kadar beklemiş olabilir ve kenar onu altmış saniye daha tutar. Pencere boyunca değişen içeriğe
gelen dört yüz seksen istek eski haritayı alır.

İkinci satır tazelik ayarlarını kısaltıyor: altmış ve üç yüz yerine on ve altmış. Pencere yetmiş
saniyeye, eski yanıt alan istek doksan üçe iniyor. Bedeli tabloda görünmüyor ama ilk tablodan
okunabilir: tazelik kısaldıkça isabet düşer ve uygulamaya inen istek artar. Tazeliği kısaltmak
pencereyi kapatmanın **pahalı** yoludur.

Üçüncü satır kaynağa geçersizleştirme gönderiyor. Kaynak önbelleği hemen temizleniyor, kenar
kendi altmış saniyesini bekliyor: pencere altmış saniye, eski yanıt alan istek seksen. Üç yüz
altmıştan altmışa inen bir kazanç, kaynağa gönderilen tek bir mesajla elde ediliyor.

Dördüncü satır kaynağa geçersizleştirme gönderirken kenar tazeliğini ona indiriyor: pencere on
saniye. Beşinci satır geçersizleştirmeyi her katmana yayıyor: pencere en yavaş kenar düğümünün
gecikmesine, **on bir saniyeye** iniyor ve kenar tazeliği artık pencereyi hiç belirlemiyor.

Buradaki sıra önemlidir. Tazelik ayarını kısaltmak pencereyi kapatır ve isabeti düşürür;
geçersizleştirmeyi yaymak pencereyi kapatır ve isabete dokunmaz. Beşinci satır altmış saniyelik
kenar tazeliğiyle çalışıyor — yani birinci satırın isabet oranıyla — ve penceresi on bir saniye.

## Yayının Kaçtığı Yer

Altıncı satır beşincinin kapatamadığını gösteriyor. Geçersizleştirme her katmana yayınlanıyor
ama bir kenar düğümü mesajı almıyor: ağ kesintisi, düğümün yeniden başlaması, kuyruğun taşması.
O düğümde pencere kenar tazeliğine geri dönüyor: **altmış saniye**.

Bu, geçersizleştirmenin getirdiği yeni yüzeydir. Tazelik süresi bir **üst sınır** verir ve hiçbir
şey yapılmasa da geçerlidir. Geçersizleştirme yayını üst sınır vermez; bir **umut** verir ve
umut tutmadığında sistem sessizce üst sınıra döner. Sistemin durumu iki düğümde on bir saniye,
bir düğümde altmış saniyedir ve dışarıdan bakan hiç kimse hangi düğüme düştüğünü bilmez.

Sonuç, tazeliğin geçersizleştirme yayınıyla birlikte **korunması** gerektiğidir. Yayın hızlı yolu
verir, tazelik geri düşüş sınırını verir. Tazeliği sonsuza çekip her şeyi yayına bağlamak, kaçan
tek bir mesajı süresiz eski içeriğe çevirir.

## Paylaşılan Anahtar Yüzeyi

Son sütunlar dersin yüzey ölçümüdür. Varsayılan önbellek anahtarı yalnız yoldur ve
`/fatura/ozet` kişiye özeldir: her abone kendi fatura özetini alır.

İlk satırda yüz altmış dokuz istek **başka bir abonenin** fatura özetini aldı; beş abonenin
verisi başkalarına gitti. Üç düğümlü ikinci satırda sızan istek doksan beşe iniyor ama sızan
abone sayısı altıya çıkıyor — bölünme sızıntıyı azaltmıyor, dağıtıyor.

Üçüncü satır en keskin olanıdır. Kaynak önbelleği eklendiğinde sızan istek yüz yetmiş dokuza
çıkıyor ve sızan abone sayısı **ikiye** iniyor. Paylaşılan tek bir kaynak girdisi, iki abonenin
faturasını üç kenar düğümüne birden dağıtıyor. Kaynak önbelleği sızıntıyı yoğunlaştırıyor: daha
az kişinin verisi, daha çok kişiye.

Bu yüzeyin adı **paylaşılan anahtar yüzeyi**dir. Açılması için bir hata gerekmez; varsayılan
anahtarın yolu içermesi ve kimliği içermemesi yeter. Yanıtın kişiye özel olduğu bilgisi
uygulamadadır, önbellekte değildir ve iki katman da bu bilgiyi sormaz.

Dördüncü satır anahtara kimliği ekliyor: sızan istek sıfır, sızan abone sıfır. Uygulamaya inen
istek ondan yirmiye çıkıyor — altı ayrı abone için altı ayrı girdi tutulduğundan tazelik
dolumları çoğalıyor. On isteklik bir bedelle yüz yetmiş dokuz sızıntı kapandı.

Beşinci satır kişiye özel içeriği hiç saklamıyor. Sızıntı yine sıfır, ama uygulamaya inen istek
**iki yüz yirmi dokuza** çıkıyor. İki güvenli seçenek arasında yirmi kat fark var ve ikisi de
aynı yüzeyi kapatıyor. Anahtarı doğru kurmak, önbelleklemeyi kapatmaktan yirmi kat ucuzdur.

## Önbelleğin Kendi Yüzeyi

İki katman uygulamanın yükünü elliden ona indirdi ve bunu yaparken dört yeni kalem getirdi.

Birincisi **saklanan yanıtın kendisidir**. Kenarda ve kaynakta artık üretilmiş yanıtlar durur;
bunlar diskte ya da bellekte bir yerdedir ve o yeri okuyabilen, uygulamanın verdiği yanıtları
kimlik doğrulamadan okur. İkincisi **geçersizleştirme kanalıdır**: bir mesaj gönderip bir girdiyi
silebilen bir uç, önceki derslerin saydığı yönetim ucu listesine iki kalem ekler — kenardaki bir
uç ve kaynaktaki bir uç. Bu uç kimliksizse, dışarıdan gönderilen bir geçersizleştirme akışı
bütün önbelleği boşaltabilir ve uygulamaya inen istek ondan iki bine çıkar.

Üçüncüsü **anahtar kuralının kendisidir**. Beşinci satırdan görüldüğü gibi kural bir
yapılandırma satırıdır ve yanlış yazıldığında hata vermez; yalnız başka bir abonenin yanıtını
döndürür. Dördüncüsü **tazelik ayarının ikiye bölünmüş olmasıdır**: pencerenin gerçek değeri iki
ayrı katmandaki iki ayrı sayıdan çıkar ve hiçbir katman tek başına o değeri bilmez.

Dört kalemin hiçbiri "önbellek açıldı" cümlesinde görünmez. Kursun kuralı burada da geçerlidir:
kapatılan yük, açılan yüzeyle birlikte yazılmadıkça karar savunulamaz. Uygulamaya inen isteği
kırk kalem azaltan bir adım, dört kalem açık yüzey ekliyorsa iki sayı da rapora aynı satırda
girmelidir.

## Özet

- Kenarı üç düğüme bölmek kenar isabetini bin dokuz yüz elliden bin sekiz yüz elli yediye
  indirdi ve uygulamaya inen isteği elliden yüz kırk üçe çıkardı; düğüm sayısı uygulama yükünü
  çarpar.
- Kaynak önbelleği yüz otuz üç isteği karşılayarak uygulamaya inen isteği ona indirdi — tek
  düğümlü düzenden de düşük; kaynak katmanının işi kenarın çoğalttığı isteği soğurmaktır.
- Geçersizleştirme yokken pencere iki tazeliğin toplamıdır: üç yüz altmış saniye ve dört yüz
  seksen eski yanıt. Kaynağa geçersizleştirme pencereyi altmışa, her katmana yayın on bir
  saniyeye indirdi.
- Tazeliği kısaltmak pencereyi kapatır ve isabeti düşürür; geçersizleştirmeyi yaymak pencereyi
  kapatır ve isabete dokunmaz — ama yayını kaçıran bir düğümde pencere sessizce tazelik süresine
  geri döner.
- Varsayılan anahtar yalnız yolu içerdiği için yüz yetmiş dokuz istek başka abonenin fatura
  özetini aldı; kaynak önbelleği sızıntıyı yoğunlaştırdı — iki abonenin verisi yüz yetmiş dokuz
  isteğe gitti.
- Anahtara kimliği eklemek sızıntıyı sıfırladı ve uygulama yükünü ona değil yirmiye çıkardı;
  kişiye özel içeriği hiç saklamamak da sızıntıyı sıfırladı ama yükü iki yüz yirmi dokuza çıkardı.

## Sonraki Adım

Bu ders trafiğe kenarda ve kaynakta iki kural koydu: neyin saklanacağı ve ne kadar tazelikle.
Kuralların ikisi de **isteğin yolunda** durdu ve dışarıdan gelen trafiğe uygulandı.

Servisler birbirine de istek gönderir. Doğrulayıcı faturalamaya, faturalama iş emrine, iş emri
bildirim geçidine bağlanır ve bu trafiğin hiçbiri kenar vekilden geçmez. Zaman aşımı, yeniden
deneme, hangi servisin hangisini çağırabileceği — bu kurallar bugün her servisin kendi kodunda
duruyor. Aynı kurallar her servisin yanına konan bir vekile taşınabilir. Sonraki ders iki
yerleşimi aynı kural değişikliği üzerinde karşılaştırır: kural değiştiğinde kaç servise
dokunulur, her isteğe kaç atlama ve kaç milisaniye eklenir, yan araba vekilinin kendisi ne
tüketir ve hangi yeni yüzeyi getirir. Üç servisli bir sistemde bedelin kazançtan büyük olduğu
nokta sayıyla gösterilir.
