---
title: 'Sunucuda Oluşturma'
source: 'https://academia.sh/tr/kurslar/olusturma-stratejileri/sunucuda-olusturma'
course: 'Oluşturma Stratejileri ve Altyapı'
language: tr
updated: '2026-08-17T18:09:31+00:00'
license: 'CC BY-SA 4.0'
---

# Sunucuda Oluşturma

İşaretlemenin isteğe yanıt verilirken üretilmesi; ilk bayt süresinin nasıl büyüdüğü, seri istek zincirinin tek tura inmesi, ağ turunun ağırlığı ve sunucunun istek başına ödediği hesaplama bedeli.

Önceki ders istemcide oluşturmanın ilk içeriğe kadar üç seri istek gerektirdiğini gösterdi:
belge, betik, veri. Bu üç isteğin ikisi, veri ile işaretlemenin ayrı taşınmasından doğar.
Sunucu veriyi zaten okuyabildiğine göre şablonu da kendisi işleyip içeriği hazır
gönderebilir.

Bu ders o değişikliği yapar ve sonucunu aynı ölçülerle sınar: ilk bayt süresi, gövde
boyutu ve belgede içeriğin bulunup bulunmaması.

## Aynı Sayfa, İki Model

Karşılaştırmanın adil olması için iki model aynı veri kaynağını, aynı gecikmeyi ve aynı
şablonu kullanır. Aşağıdaki sunucu her ikisini de sunar: `/istemci` yolu boş kabuğu,
`/sunucu` yolu işaretlemesi hazır belgeyi verir.

```js
// iki-model.mjs — ayni istasyon sayfasini iki modelde sunan tek sunucu
import { createServer } from "node:http";

const OLCUMLER = [
  { zaman: "06:00", sicaklik: -4.2, nem: 72 },
  { zaman: "07:00", sicaklik: -3.8, nem: 70 },
  { zaman: "08:00", sicaklik: -2.1, nem: 66 },
];

const bekle = (ms) => new Promise((c) => setTimeout(c, ms));
const okuOlcumler = async () => { await bekle(40); return OLCUMLER; }; // veri kaynagi isi

const liste = (olcumler) =>
  olcumler.map((o) => `<li>${o.zaman} ${o.sicaklik} C, %${o.nem}</li>`).join("");

const belge = (govde, betik) => `<!doctype html>
<html lang="tr"><head><meta charset="utf-8"><title>Kuzey Yamac Olcum Istasyonu</title>
<script src="${betik}" defer></script></head>
<body>${govde}</body></html>
`;

const KABUK = belge('<div id="istasyon"></div>', "/uygulama.js");

const BETIK_ISTEMCI = `const kok = document.getElementById("istasyon");
const olcumler = await (await fetch("/api/olcumler")).json();
kok.innerHTML = "<h1>Kuzey Yamac Olcum Istasyonu</h1><ul>" +
  olcumler.map((o) => "<li>" + o.zaman + " " + o.sicaklik + " C, %" + o.nem + "</li>").join("") +
  "</ul>";
`;

const BETIK_SUNUCU = `document.querySelector("#yenile")
  .addEventListener("click", () => location.reload());
`;

const gonder = (yanit, tip, govde) => {
  yanit.setHeader("Content-Type", tip);
  yanit.setHeader("Content-Length", Buffer.byteLength(govde));
  yanit.writeHead(200).end(govde);
};

const HTML = "text/html; charset=utf-8";
const JS = "text/javascript; charset=utf-8";

createServer(async (istek, yanit) => {
  yanit.sendDate = false;
  switch (istek.url) {
    case "/istemci":
      return gonder(yanit, HTML, KABUK);
    case "/uygulama.js":
      return gonder(yanit, JS, BETIK_ISTEMCI);
    case "/api/olcumler":
      return gonder(yanit, "application/json", JSON.stringify(await okuOlcumler()));
    case "/sunucu": {
      const olcumler = await okuOlcumler();
      const govde = `<div id="istasyon"><h1>Kuzey Yamac Olcum Istasyonu</h1>` +
        `<ul>${liste(olcumler)}</ul><button id="yenile">Yenile</button></div>`;
      return gonder(yanit, HTML, belge(govde, "/etkilesim.js"));
    }
    case "/etkilesim.js":
      return gonder(yanit, JS, BETIK_SUNUCU);
    default:
      return yanit.writeHead(404).end();
  }
}).listen(8172, "127.0.0.1", () => console.log("dinleniyor: 127.0.0.1:8172"));
```

Tek fark, `/sunucu` dalının veriyi yanıt üretilirken okuyup listeyi işaretlemeye
yazmasıdır. Şablon işlevi ikisinde de aynıdır; ayrı olan, çağrıldığı yerdir.

## Ölçüm

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

```bash
#!/usr/bin/env bash
# iki-model.mjs'yi baslatir, iki modeli ayni olculerle karsilastirir, sonra durdurur.
node iki-model.mjs > /dev/null &
sunucu=$!
sleep 1
curl -sS -o /dev/null http://127.0.0.1:8172/istemci   # isinma istegi: olcume girmez

BICIM='ilk bayt %{time_starttransfer} s   govde %{size_download} B\n'

echo "--- istemcide olusturma: ilk belge ---"
curl -sS -o /dev/null -w "$BICIM" http://127.0.0.1:8172/istemci
echo "belgede gecen olcum degeri sayisi: $(curl -sS http://127.0.0.1:8172/istemci | grep -o -- '-4.2\|-3.8\|-2.1' | wc -l | tr -d ' ')"

echo "--- sunucuda olusturma: ilk belge ---"
curl -sS -o /dev/null -w "$BICIM" http://127.0.0.1:8172/sunucu
echo "belgede gecen olcum degeri sayisi: $(curl -sS http://127.0.0.1:8172/sunucu | grep -o -- '-4.2\|-3.8\|-2.1' | wc -l | tr -d ' ')"

echo "--- sunucuda uretilmis govde ---"
curl -sS http://127.0.0.1:8172/sunucu

echo "--- istemci modelinde icerige kadar uc istegin toplami ---"
toplam=0
for yol in /istemci /uygulama.js /api/olcumler; do
  s=$(curl -sS -o /dev/null -w '%{time_starttransfer}' "http://127.0.0.1:8172$yol")
  printf '  %-14s %s s\n' "$yol" "$s"
  toplam=$(echo "$toplam + $s" | bc)
done
printf '  %-14s %s s\n' "toplam" "$toplam"

kill "$sunucu"
```

```
--- istemcide olusturma: ilk belge ---
ilk bayt 0.000909 s   govde 199 B
belgede gecen olcum degeri sayisi: 0
--- sunucuda olusturma: ilk belge ---
ilk bayt 0.042922 s   govde 358 B
belgede gecen olcum degeri sayisi: 3
--- sunucuda uretilmis govde ---
<!doctype html>
<html lang="tr"><head><meta charset="utf-8"><title>Kuzey Yamac Olcum Istasyonu</title>
<script src="/etkilesim.js" defer></script></head>
<body><div id="istasyon"><h1>Kuzey Yamac Olcum Istasyonu</h1><ul><li>06:00 -4.2 C, %72</li><li>07:00 -3.8 C, %70</li><li>08:00 -2.1 C, %66</li></ul><button id="yenile">Yenile</button></div></body></html>
--- istemci modelinde icerige kadar uc istegin toplami ---
  /istemci       0.000837 s
  /uygulama.js   0.000796 s
  /api/olcumler  0.042007 s
  toplam         .043640 s
```

Süre alanları makineye ve o andaki yüke bağlıdır; her çalıştırmada farklı çıkar. Yorumu
oranlar taşır.

Üç değişiklik ölçülmüştür. **İlk bayt süresi iki mertebe uzamıştır** — 0,0009 saniyeden
0,0429 saniyeye: boş kabuk için sunucu hiçbir iş yapmaz, hazır belge içinse veri kaynağını
beklemek zorundadır. Kabuğun süresi yerel bağlantının gürültü tabanındadır ve çalıştırmadan
çalıştırmaya belirgin biçimde oynar; sabit kalan, sunucuda oluşturmada ilk baytın **veri
kaynağının işi kadar** gecikmesidir. **Gövde yaklaşık 1,8 kat büyümüştür**: işaretleme artık
üç ölçüm satırını da taşır. **Belgede içerik vardır**: istemci modelinde sıfır olan ölçüm
değeri sayısı üçtür.

## Ağ Turu Olmayan Bir Ölçümün Sınırı

Son bölüm dikkatle okunmalıdır. İstemci modelinde içeriğe kadar geçen toplam süre 0,0436
saniyedir; sunucu modelinin tek isteği 0,0429 saniye sürer. İkisi neredeyse aynıdır.

Bunun nedeni ölçümün geri döngü arayüzünde yapılmasıdır: 127.0.0.1 adresine yapılan bir
istekte ağ turu sıfıra yakındır. Ölçüm bu yüzden yalnızca **sunucu işini** yalıtır ve
sunucu işi iki modelde de aynı 40 milisaniyedir. Sunucuda oluşturmanın kazancı sunucu
işinden değil, **kaç kez gidip gelindiğinden** doğar.

Turun ağırlığı ayrıca hesaplanır. Aşağıdaki hesabın girdileri yukarıdaki ölçümden ve
önceki dersteki betik varsayımlarından gelir.

```js
// tur-etkisi.mjs — ag turunun iki modeldeki agirligi
// Sunucu isi ve aktarim, l02'deki yerel olcumden alinmistir: veri isi 42 ms,
// kabuk ve belge aktarimi yerel baglantida 1 ms'nin altinda kaldigi icin 1 ms sayildi.
const VERI_ISI = 42;      // ms
const AKTARIM = 1;        // ms, her yanit icin
const BETIK_INDIRME = 117; // ms, 180 KB / 1.5 MB/s
const BETIK_YURUTME = 63;  // ms

// istemci modeli: belge turu + betik turu + veri turu, arada betik indirme ve yurutme
const istemci = (tur) =>
  tur + AKTARIM + tur + BETIK_INDIRME + BETIK_YURUTME + tur + VERI_ISI + AKTARIM;

// sunucu modeli: tek tur, sunucu veriyi okur ve isaretlemeyi hazir gonderir
const sunucu = (tur) => tur + VERI_ISI + AKTARIM;

console.log("ag turu".padEnd(10) + "istemci".padStart(10) + "sunucu".padStart(10) +
  "fark".padStart(10) + "oran".padStart(8));
for (const tur of [0, 20, 60, 150]) {
  const i = istemci(tur), s = sunucu(tur);
  console.log(`${tur} ms`.padEnd(10) + `${i} ms`.padStart(10) + `${s} ms`.padStart(10) +
    `${i - s} ms`.padStart(10) + (i / s).toFixed(1).padStart(8));
}
```

```
ag turu      istemci    sunucu      fark    oran
0 ms          224 ms     43 ms    181 ms     5.2
20 ms         284 ms     63 ms    221 ms     4.5
60 ms         404 ms    103 ms    301 ms     3.9
150 ms        674 ms    193 ms    481 ms     3.5
```

Tablo iki şeyi aynı anda söyler. Mutlak fark tur uzadıkça **büyür**: 150 milisaniyelik bir
turda aradaki uçurum yarım saniyeye yaklaşır. Oran ise **küçülür**, çünkü tur her iki
modele de eklenir ve payda da büyür. Sıfır turluk satır, betik indirme ile yürütmenin tek
başına 180 milisaniye tuttuğunu gösterir: bu kalem ağ hiç olmasa bile durmaz.

## Sunucunun Ödediği Bedel

Kazanılan sürenin bir faturası vardır ve bu fatura istek başınadır.

**Hesaplama işi tekrarlanır.** Boş kabuk her kullanıcı için aynı bayt dizisidir ve bir kez
üretilip sonsuza kadar sunulabilir. Sunucuda üretilen belge her istekte yeniden kurulur:
veri okunur, şablon işlenir, dizgi birleştirilir. İstek hacmi arttıkça bu iş doğrusal
büyür ve sunucunun boyutlandırılmasını belirleyen kalem hâline gelir.

**Yanıt önbelleklenmesi zorlaşır.** Önbellek Stratejileri dersinde kurulan ayrım burada
karşılığını bulur: boş kabuk uzun ömürle saklanabilen bir varlıktır, sunucuda üretilmiş
belge ise değişken içeriktir. İçerik kişiye göre değişiyorsa yanıt hiçbir paylaşımlı
katmanda saklanamaz; değişmiyorsa saklanabilir ama tazelik penceresi içeriğin değişme
sıklığıyla sınırlıdır. Kişiselleştirmenin sayfanın tamamına mı yoksa küçük bir bölümüne mi
dokunduğu, bu yüzden bir tasarım kararıdır.

**Veri kaynağının gecikmesi doğrudan ilk bayt süresine yazılır.** İstemci modelinde
kullanıcı beklerken en azından bir kabuk görür; sunucu modelinde veri kaynağı yavaşladığında
kullanıcı hiçbir şey görmez, çünkü ilk bayt henüz yollanmamıştır. Yanıtın tamamı tek
parçada üretildiği sürece bu bağımlılık kırılamaz.

**Hata alanı genişler.** Veri kaynağı yanıt vermediğinde istemci modelinde kabuk yüklenir
ve arayüz bir hata durumu gösterebilir; sunucu modelinde belgenin kendisi üretilemez. Bu
yüzden sunucuda oluşturan bir uç, veri çağrılarına zaman aşımı koyar ve eksik veriyle de
üretilebilecek bir yedek işaretleme tanımlar.

## Gelen İşaretleme Etkileşimli Değildir

Ölçülen gövdede bir düğme vardır ama düğme çalışmaz. İşaretleme sunucuda üretilmiştir;
olay dinleyicileri istemcide, betik yürüdükten sonra bağlanır. Belge ekrana geldiği an ile
düğmenin yanıt verdiği an arasında bir aralık kalır.

Bu aralık modelin doğal sonucudur ve ölçülebilir iki büyüklüğü ayırır: **ilk içerik
boyaması** belgenin gelmesiyle gerçekleşir, **etkileşime hazır olma** betiğin yürümesini
bekler. Sunucuda oluşturma birinciyi öne çeker, ikinciyi olduğu yerde bırakır. Aradaki
boşlukta kullanıcı içeriği görür, tıklar ve tepki alamaz.

Boşluğun uzunluğu betiğin boyutuna ve aygıtın gücüne bağlıdır. Beşinci ders bu boşluğu
adlandırır ve daraltmanın yollarını ele alır.

## Özet

- Sunucuda oluşturmada işaretleme isteğe yanıt verilirken üretilir; belge içeriği taşır ve
  ilk içeriğe kadar tek ağ turu yeter.
- Ölçüm, ilk bayt süresinin veri kaynağının işi kadar uzadığını, gövdenin büyüdüğünü ve
  ölçüm değerlerinin işaretlemede göründüğünü gösterir.
- Geri döngü arayüzünde yapılan bir ölçüm ağ turunu yalıtır; iki modelin farkı tur maliyeti
  arttıkça mutlak olarak büyür, oransal olarak küçülür.
- Bedel istek başınadır: hesaplama tekrarlanır, yanıtın önbelleklenebilirliği içeriğin
  değişkenliğiyle sınırlanır ve veri kaynağının gecikmesi doğrudan ilk bayta yazılır.
- Sunucudan gelen işaretleme etkileşimli değildir; ilk içerik boyası ile etkileşime hazır
  olma arasında betiğin yürümesini bekleyen bir aralık kalır.

## Sonraki Adım

Sunucuda oluşturma, her istekte aynı işi yapmayı göze alır. İstasyonun tanıtım sayfası ile
geçmiş günlerin arşiv sayfaları için bu israftır: içerikleri isteğe göre değişmez, aynı
girdiden hep aynı işaretleme çıkar. Aynı çıktıyı üreten bir hesabın istek başına
tekrarlanması yerine bir kez yapılıp dosyaya yazılması mümkündür. Sonraki ders bu kaymayı
inceler: iş, isteğin geldiği andan derleme anına taşındığında ilk bayt süresine ne olur,
ve bedel nereye — derleme süresine mi, tazeliğe mi — yazılır?
