---
title: 'Önbellek Stratejileri'
source: 'https://academia.sh/tr/kurslar/tarayici-platformu/onbellek-stratejileri'
course: 'Tarayıcı ve Web Platformu'
language: tr
updated: '2026-08-17T18:09:12+00:00'
license: 'CC BY-SA 4.0'
---

# Önbellek Stratejileri

Tarayıcıdaki iki önbellek katmanının iş bölümü, başlıklarla verilen tazelik kararı ve koşullu istek, önbellek anahtarının üretimi, dört stratejinin aynı durumlarda verdiği sonuç ve sürümleme ile temizlik.

Önceki ders araya girme yetkisini kurdu, onunla ne yapılacağını açık bıraktı. İsteği
karşılamanın tek bir doğru biçimi yoktur: istasyonun logosu ile ölçüm listesi aynı kuralla
sunulamaz. Biri değişmez ve ağdan sorulması gereksizdir; diğeri dakikada bir değişir ve
eski kopyası yanıltıcıdır.

Bu ders, kaynak başına verilen bu kararı iki soruya indirir: bir kopya nereden bulunur ve
ne zaman taze sayılır.

## İki Ayrı Önbellek Katmanı

Tarayıcıda iki ayrı önbellek vardır ve karıştırılmaları yanlış tanılara yol açar.

**HTTP önbelleği**, tarayıcının kendi yönettiği ve program tarafından görülmeyen
katmandır. Neyin ne kadar saklanacağını sunucunun gönderdiği başlıklar belirler; sayfa
kodunun sözü geçmez. Bir kaydı silmenin ya da içeriğini okumanın program yolu yoktur.

**Program denetimli önbellek**, servis çalışanının açıkça yazdığı ve sildiği ad–kayıt
deposudur. Ne saklanacağına, ne kadar tutulacağına ve ne zaman sunulacağına yazan kod
karar verir; başlıklar bu katmanda kendiliğinden hiçbir şey yapmaz.

İkisi bir zincirde durur. Servis çalışanı ağa çıktığında istek HTTP önbelleğinden
geçer. Bu, ikili önbellekleme üretir: aynı kaynak iki katmanda da saklanabilir ve program
katmanına yazılan kopya, HTTP katmanının eski kopyası olabilir. Kaçınmanın yolu, kritik
kaynakları önbelleğe alırken isteği HTTP katmanını atlayacak biçimde kurmaktır.

## Tazelik Kararı Nerede Verilir

HTTP katmanının kararı üç başlığa dayanır: saklama izni, ömür ve doğrulayıcı. Bunlar bir
yanıtın başlıklarında okunabilir.

```js
// sunucu.mjs — uc kaynagi uc ayri tazelik politikasiyla sunan yerel sunucu
import { createServer } from "node:http";

const KAYNAKLAR = {
  "/logo.svg": {
    tip: "image/svg+xml",
    etiket: '"logo-3f2a"',
    denetim: "public, max-age=31536000, immutable",
    govde: '<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"></svg>',
  },
  "/olcumler.json": {
    tip: "application/json",
    etiket: '"olcum-7"',
    denetim: "no-cache",
    govde: '{"sicaklik":-4.2,"nem":72}',
  },
  "/oturum": {
    tip: "text/plain; charset=utf-8",
    etiket: null,
    denetim: "no-store",
    govde: "kisiye ozel icerik",
  },
};

createServer((istek, yanit) => {
  yanit.sendDate = false; // ciktiyi belirlenimci kilmak icin: Date basligi yazilmaz
  const kaynak = KAYNAKLAR[istek.url];
  if (!kaynak) { yanit.writeHead(404).end(); return; }

  yanit.setHeader("Cache-Control", kaynak.denetim);
  if (kaynak.etiket) yanit.setHeader("ETag", kaynak.etiket);

  // Kosullu istek: istemcinin elindeki etiket sunucudakiyle ayniysa govde gonderilmez.
  if (kaynak.etiket && istek.headers["if-none-match"] === kaynak.etiket) {
    yanit.writeHead(304).end();
    return;
  }
  yanit.setHeader("Content-Type", kaynak.tip);
  yanit.setHeader("Content-Length", Buffer.byteLength(kaynak.govde));
  yanit.writeHead(200).end(kaynak.govde);
}).listen(8137, "127.0.0.1", () => console.log("dinleniyor: 127.0.0.1:8137"));
```

Aşağıdaki betik bu dosyayla aynı dizinde çalıştırılır. Bağlantı noktası olarak seçilen
8137 keyfîdir ve boş olmalıdır; kullanımdaysa iki dosyada da değiştirilir.

```bash
#!/usr/bin/env bash
# sunucu.mjs'yi baslatir, uc kaynagin yanit basliklarini okur, sonra durdurur.
node sunucu.mjs > /dev/null &
sunucu=$!
sleep 1

echo "--- /logo.svg (surumlenmis varlik) ---"
curl -sS -D - -o /dev/null http://127.0.0.1:8137/logo.svg

echo "--- /olcumler.json (her kullanimda dogrulanir) ---"
curl -sS -D - -o /dev/null http://127.0.0.1:8137/olcumler.json

echo '--- /olcumler.json + If-None-Match: "olcum-7" ---'
curl -sS -D - -o /dev/null -H 'If-None-Match: "olcum-7"' http://127.0.0.1:8137/olcumler.json

echo "--- /oturum (hic saklanmaz) ---"
curl -sS -D - -o /dev/null http://127.0.0.1:8137/oturum

kill "$sunucu"
```

```
--- /logo.svg (surumlenmis varlik) ---
HTTP/1.1 200 OK
Cache-Control: public, max-age=31536000, immutable
ETag: "logo-3f2a"
Content-Type: image/svg+xml
Content-Length: 67
Connection: keep-alive
Keep-Alive: timeout=5

--- /olcumler.json (her kullanimda dogrulanir) ---
HTTP/1.1 200 OK
Cache-Control: no-cache
ETag: "olcum-7"
Content-Type: application/json
Content-Length: 26
Connection: keep-alive
Keep-Alive: timeout=5

--- /olcumler.json + If-None-Match: "olcum-7" ---
HTTP/1.1 304 Not Modified
Cache-Control: no-cache
ETag: "olcum-7"
Connection: keep-alive
Keep-Alive: timeout=5

--- /oturum (hic saklanmaz) ---
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: text/plain; charset=utf-8
Content-Length: 18
Connection: keep-alive
Keep-Alive: timeout=5
```

Bağlantıya ilişkin iki başlık taşıyıcı katmandan gelir ve tazelikle ilgisi yoktur; `Date`
başlığı çıktının her çalıştırmada aynı olması için bilerek kapatılmıştır, gerçek bir
sunucuda bulunur.

Üç politika üç ayrı kaynak sınıfını temsil eder. Adı sürümlenmiş bir varlık uzun ömür
alır ve içeriği hiç değişmeyeceği bildirilir; böyle bir kaynak için doğrulama isteği bile
gereksizdir. Sık değişen veri saklanabilir ama **her kullanımda doğrulanmalıdır** —
başlığın adı yanıltıcıdır, saklamayı değil doğrulamasız kullanmayı yasaklar. Kişiye özel
içerik hiçbir katmanda saklanmaz.

Üçüncü isteğin yanıtı doğrulamanın kazancını gösterir: istemci elindeki doğrulayıcıyı
gönderir, sunucu içerik değişmediğini gövdesiz bir yanıtla bildirir. Ağ turu yapılmıştır
ama gövde aktarılmamıştır. Bu, gecikmeyi ortadan kaldırmaz, bant genişliğini kurtarır;
kopan bir bağlantıda doğrulama da yapılamayacağı için tek başına çevrimdışı davranış
sağlamaz.

## Önbellek Anahtarı

Program denetimli önbellekte bir kaydın anahtarı bir istektir, ve eşleme öntanımlı olarak
**adresin tamamı** üzerinden yapılır. Bunun üç sonucu vardır.

Birincisi, sorgu dizgisi anahtarın parçasıdır. `/olcumler?tur=sicaklik` ile
`/olcumler?tur=nem` iki ayrı kayıttır. Aynı kaynağa yönlendirdiği bilinen sorgu
parametreleri varsa eşlemede sorgunun göz ardı edilmesi istenebilir; bu, izleme
parametreleri yüzünden aynı sayfanın onlarca kez saklanmasını önler.

İkincisi, aynı adresin farklı yöntemlerle yapılan istekleri ayrılabilir; önbellek
öntanımlı olarak yalnızca güvenli yöntemleri saklamaya elverişlidir. Gövdeli bir isteğin
yanıtını adres anahtarıyla saklamak, farklı gövdelerin aynı kayda düşmesi demektir.

Üçüncüsü, sunucu bir yanıtın hangi istek başlığına göre değiştiğini bildirebilir. Dil
tercihine ya da kabul edilen içerik biçimine göre farklı yanıt veren bir uç için bu
bildirim yapılmazsa, bir kullanıcının aldığı yanıt diğerine sunulur. Eşleme sırasında bu
bildirimin dikkate alınıp alınmayacağı da seçilebilir.

Anahtar üretimini kendi eline alan bir çalışan, adresi yazmadan önce normalleştirir:
izleme parametrelerini atar, kalan parametreleri sıraya koyar, adres parçasını siler.
Aynı içeriğin tek anahtara düşmesi, hem yeri hem de isabet oranını iyileştirir.

## Dört Strateji ve Verdikleri Söz

İsteği karşılamanın dört temel biçimi vardır. Aralarındaki fark, aynı üç durumda ne
sundukları ve ağı ne zaman kullandıklarıyla görünür hâle gelir.

```js
// strateji.mjs — dort onbellek stratejisinin ayni uc durumda verdigi sonuc
const ADRES = "/istasyon/olcumler.json";

function kur({ onbelleklenmis, cevrimici }) {
  const durum = { agCagrisi: 0, onbellek: new Map() };
  if (onbelleklenmis) durum.onbellek.set(ADRES, "v1");
  durum.ag = async () => {
    durum.agCagrisi += 1;
    if (!cevrimici) throw new Error("ag yok");
    return "v2";
  };
  return durum;
}

async function onbellekOnce(d) {
  const kayit = d.onbellek.get(ADRES);
  if (kayit) return kayit;
  const yanit = await d.ag();
  d.onbellek.set(ADRES, yanit);
  return yanit;
}

async function agOnce(d) {
  try {
    const yanit = await d.ag();
    d.onbellek.set(ADRES, yanit);
    return yanit;
  } catch {
    return d.onbellek.get(ADRES) ?? "(yedek sayfa)";
  }
}

async function yenidenDogrulayarakSun(d) {
  const kayit = d.onbellek.get(ADRES);
  const tazeleme = d.ag().then((yanit) => d.onbellek.set(ADRES, yanit)).catch(() => {});
  if (kayit) return kayit;          // bekletmeden eski kopya verilir
  await tazeleme;
  return d.onbellek.get(ADRES) ?? "(yedek sayfa)";
}

async function yalnizAg(d) {
  try { return await d.ag(); } catch { return "(yedek sayfa)"; }
}

const stratejiler = [
  ["onbellek once", onbellekOnce],
  ["ag once", agOnce],
  ["yeniden dogrulayarak sun", yenidenDogrulayarakSun],
  ["yalniz ag", yalnizAg],
];

const durumlar = [
  ["onbellek bos, cevrimici", { onbelleklenmis: false, cevrimici: true }],
  ["onbellekte v1, cevrimici", { onbelleklenmis: true, cevrimici: true }],
  ["onbellekte v1, cevrimdisi", { onbelleklenmis: true, cevrimici: false }],
];

console.log("strateji".padEnd(26) + "durum".padEnd(28) + "sunulan".padEnd(16) + "ag  onbellekte kalan");
for (const [stratejiAdi, calistir] of stratejiler) {
  for (const [durumAdi, secenek] of durumlar) {
    const d = kur(secenek);
    const sunulan = await calistir(d);
    await new Promise((c) => setImmediate(c)); // arka plandaki tazeleme bitsin
    console.log(
      stratejiAdi.padEnd(26) + durumAdi.padEnd(28) +
      String(sunulan).padEnd(16) + String(d.agCagrisi).padEnd(4) +
      (d.onbellek.get(ADRES) ?? "(bos)"));
  }
}
```

```
strateji                  durum                       sunulan         ag  onbellekte kalan
onbellek once             onbellek bos, cevrimici     v2              1   v2
onbellek once             onbellekte v1, cevrimici    v1              0   v1
onbellek once             onbellekte v1, cevrimdisi   v1              0   v1
ag once                   onbellek bos, cevrimici     v2              1   v2
ag once                   onbellekte v1, cevrimici    v2              1   v2
ag once                   onbellekte v1, cevrimdisi   v1              1   v1
yeniden dogrulayarak sun  onbellek bos, cevrimici     v2              1   v2
yeniden dogrulayarak sun  onbellekte v1, cevrimici    v1              1   v2
yeniden dogrulayarak sun  onbellekte v1, cevrimdisi   v1              1   v1
yalniz ag                 onbellek bos, cevrimici     v2              1   (bos)
yalniz ag                 onbellekte v1, cevrimici    v2              1   v1
yalniz ag                 onbellekte v1, cevrimdisi   (yedek sayfa)   1   v1
```

İkinci satır **önbellek önce** stratejisinin belirleyici özelliğidir: kopya varken ağ hiç
kullanılmaz. Yanıt en hızlı biçimde gelir ve bağlantıdan bağımsızdır; bedeli, kaynak
sunucuda değişse bile eski kopyanın süresiz sunulmasıdır. Bu yüzden yalnızca adı
sürümlenmiş, içeriği asla değişmeyen varlıklar için doğrudur.

Beşinci ve altıncı satır **ağ önce** stratejisini özetler: çevrimiçiyken her zaman
güncel, çevrimdışıyken elde ne varsa. Ağın yavaş olduğu durumda kullanıcı ağın gecikmesi
kadar bekler; gerçek dağıtımlarda bu bekleme bir zaman aşımıyla sınırlanır ve süre dolunca
kopyaya düşülür.

Sekizinci satır **yeniden doğrulayarak sunma** stratejisinin ödünleşimini tek satırda
gösterir: sunulan `v1`, önbellekte kalan `v2`. Kullanıcı beklemeden yanıt alır ama bir
sürüm geriden gelir; güncel içerik bir sonraki ziyarette görünür. Bu, tazeliğin bir tur
gecikmesine razı olunabilen içerik için doğru seçimdir ve arayüzün bunu üstü kapalı
bırakmaması gerekir.

Son üç satır **yalnız ağ** stratejisinin önbelleği hiç yazmadığını gösterir: üçüncü
durumda önbellekte `v1` durduğu hâlde yedek sayfa sunulmuştur. Ölçüm gönderimi gibi
biriktirilemeyen istekler bu stratejiye aittir; çevrimdışıyken yapılacak şey eski veriyi
göstermek değil, isteğin gerçekleşmediğini bildirmektir.

## Sürümleme, Temizlik ve Kota

Önbellekler adlandırılır ve ad sürüm taşır. Yeni bir çalışan sürümü kurulurken kendi adına
yazar; etkinleşirken kendi adı dışındaki bütün önbellekleri siler. Bu iki adım birlikte,
eski ve yeni varlıkların karışmasını önler: bir sürümün varlıkları ya tümüyle vardır ya
tümüyle yoktur.

Kurulum sırasında toplanan kaynak listesi kısa tutulur. Uygulamanın açılması için gereken
en küçük küme — belge kabuğu, temel biçem, temel betik, çevrimdışı yedek sayfa — kuruluma
girer; geri kalan varlıklar kullanıldıkça yazılır. Kurulumun bir bütün olarak başarısız
sayılması, uzun bir listenin tek bir kalemi yüzünden bütün dağıtımı engellemesi anlamına
gelir.

Depolanan verinin sınırsız olmadığı da hesaba katılır. Tarayıcı köken başına bir üst sınır
uygular ve yer daraldığında kökenin verisini bütün olarak silebilir. Buradan iki kural
çıkar: önbellek kalıcı bir veritabanı gibi kullanılmaz, ve önbellekten okunan bir kaydın
bulunamama olasılığı her zaman ele alınır.

## Özet

- Tarayıcıda iki önbellek katmanı vardır: başlıklarla yönetilen HTTP önbelleği ve kodla
  yönetilen program denetimli önbellek; ikisi zincirde arka arkaya durur.
- Tazelik başlıkları üç kararı bildirir: saklanabilir mi, ne kadar taze sayılır, hangi
  doğrulayıcıyla sınanır. Doğrulama gövdesiz bir yanıtla sonuçlanır ve bant genişliğini
  kurtarır, gecikmeyi kaldırmaz.
- Önbellek anahtarı öntanımlı olarak adresin tamamıdır; sorgu dizgisi anahtarın
  parçasıdır ve normalleştirilmediğinde aynı içerik birden çok kayda düşer.
- Önbellek önce en hızlı ve en eskiye açık, ağ önce en taze ve en yavaş, yeniden
  doğrulayarak sunma hızlı ama bir sürüm geriden, yalnız ağ ise çevrimdışı davranışı
  olmayan stratejidir.
- Önbellek adları sürüm taşır; kurulumda yazılır, etkinleşmede eski adlar silinir. Kurulum
  listesi kısa tutulur ve depolama sınırlıdır.

## Sonraki Adım

Bu ders sayfayı ağdan bağımsızlaştırdı: kaynaklar yerelde, kararlar tanımlı. Ortaya çıkan
şey artık bir sayfadan fazlasıdır ve kullanıcıya da öyle görünmesi gerekir. Kuzey Yamaç
sayfasını sahada kullanan kişi onu her seferinde adres yazarak açmak istemez; kendi
penceresinde, kendi simgesiyle, tarayıcı arayüzü olmadan açılmasını bekler. Bunun için
sayfanın kendini tanıtan bir bildirim dosyası, kurulabilirliğin ölçütleri ve arka plandan
gelen bildirimlere ilişkin bir izin modeli gerekir. Sonraki ders bu üç parçayı ele alır.
