---
title: 'Sunucu Gerektiren Dağıtım'
source: 'https://academia.sh/tr/kurslar/olusturma-stratejileri/sunucu-gerektiren-dagitim'
course: 'Oluşturma Stratejileri ve Altyapı'
language: tr
updated: '2026-08-17T18:09:30+00:00'
license: 'CC BY-SA 4.0'
---

# Sunucu Gerektiren Dağıtım

İstek anında çalışan kodun barındırılma biçimleri; uzun ömürlü süreç, istek başına örnek ve kenar çalışma zamanının soğuk başlatma, gecikme, ayrılmış kapasite ve durum tutma eksenlerinde ölçülmesi, hazırlık ucu ile zarif kapanma sırası.

Statik barındırmanın dışarıda bıraktığı her iş, istek anında çalışan bir koda ihtiyaç duyar.
Kuzey Yamaç sitesinde bunlar arşiv yazma ucu, oturum yenileme ve yetkiye bağlı düzenleme
görünümleridir; ortak özellikleri gizli değer kullanmaları ve yanıtı isteğe göre
üretmeleridir.

Bu ders o kodun nerede çalışacağını sorar. Üç seçenek vardır ve aralarındaki fark bir tercih
meselesi değil, ölçülebilir bir davranış farkıdır.

## Üç Barındırma Biçimi

**Uzun ömürlü süreç.** Belirli sayıda örnek sürekli ayakta durur ve gelen istekleri
aralarında paylaşır. Her örnek eşzamanlı olarak çok sayıda isteği yürütebilir; toplam
kapasite, örnek sayısı ile örnek başına eşzamanlılık sınırının çarpımıdır. Bu kapasite
isteğin gelip gelmemesinden bağımsız olarak ayrılmıştır. Süreç ayakta kaldığı için bellekte
durum tutabilir, veri deposuna bir bağlantı havuzu açık tutabilir.

**İstek başına örnek.** İstek geldiğinde bir örnek ayağa kaldırılır, isteği işler, ardından
bir süre boşta bekler ve sönme sırasına girer. Örnek başına eşzamanlılık genellikle birdir;
eşzamanlı iki istek iki örnek demektir. Ayakta örnek yoksa **soğuk başlatma (cold start)**
ödenir — Kenar Oluşturma dersinde başlatma süresi olarak anılan kalem budur. Ayrılmış
kapasite talebi izler, ama boşta bekleme süresi kadar gecikmeyle.

**Kenar çalışma zamanı.** Aynı örnek modeli, çok sayıda düğüme dağıtılmış hâlidir. Soğuk
başlatma çok daha kısadır, çünkü çalıştırılan kodun bütçesi dardır. Karşılığında veri
kaynağı uzaktadır: Kenar Oluşturma dersinin kuralı gereği, veri kenara taşınamadığı ölçüde
her istek o mesafeyi öder.

## Aynı Yükü Üç Biçimde Yürütmek

Üç biçim aynı yük izi üzerinde ölçülebilir. Aşağıdaki benzetim sanal saat kullanır; gerçek
zaman okunmadığı için çıktı her koşuda aynıdır.

```js
// calisma-zamani.mjs — ayni yuku uc calisma zamani biciminde yurutur.
// Sanal saat kullanilir; Date.now() cagrilmaz, sonuc her kosuda aynidir.

// Belirlenimci uretec (splitmix32). Tohum sabit oldugu icin varis izi degismez.
function uretec(tohum) {
  let s = tohum >>> 0;
  return () => {
    s = (s + 0x9e3779b9) >>> 0;
    let z = s;
    z = Math.imul(z ^ (z >>> 16), 0x21f0aaad) >>> 0;
    z = Math.imul(z ^ (z >>> 15), 0x735a2d97) >>> 0;
    return ((z ^ (z >>> 15)) >>> 0) / 4294967296;
  };
}

const SURE = 600_000; // ms
const HIZMET = 120;   // ms, isin kendisi: veri okuma + sablon
const PENCERE = [
  ["seyrek", 0, 200_000, 0.5],
  ["duzenli", 200_000, 400_000, 60],
  ["patlama", 400_000, 410_000, 600],
  ["toparlanma", 410_000, 600_000, 60],
];

const hizi = (t) => PENCERE.find(([, a, b]) => t >= a && t < b)[3];

// Varis izi: usel araliklar, pencereye gore degisen hizla.
function varislar() {
  const r = uretec(20_260_327);
  const liste = [];
  let t = 0;
  while (t < SURE) {
    t += (-Math.log(1 - r()) / hizi(t)) * 1000;
    if (t < SURE) liste.push(t);
  }
  return liste;
}

// 1) Uzun omurlu surec: sabit sayida yuva hep ayrilidir, soguk baslatma yoktur,
//    yuvalar dolduysa istek kuyrukta bekler.
function uzunOmurlu(varis, { yuva, hizmet }) {
  const bos = new Array(yuva).fill(0);
  const kayit = [];
  for (const t of varis) {
    let k = 0;
    for (let i = 1; i < yuva; i++) if (bos[i] < bos[k]) k = i;
    const baslangic = Math.max(t, bos[k]);
    kayit.push({ t, gecikme: baslangic - t + hizmet, soguk: false });
    bos[k] = baslangic + hizmet;
  }
  return { kayit, araliklar: new Array(yuva).fill([0, SURE]) };
}

// 2) Istek basina ornek: bir ornek tek istek isler, isi bitince bostaOmur kadar
//    sicak bekler, sonra sonar. Sicak ornek yoksa soguk baslatma odenir.
function istekBasina(varis, { hizmet, soguk, bostaOmur }) {
  const kayit = [], araliklar = [];
  let canli = [];
  for (const t of varis) {
    canli = canli.filter((o) => {
      if (o.omurSonu > t) return true;
      araliklar.push([o.olusma, o.omurSonu]);
      return false;
    });
    const sicak = canli.find((o) => o.mesgulSonu <= t);
    if (sicak) {
      kayit.push({ t, gecikme: hizmet, soguk: false });
      sicak.mesgulSonu = t + hizmet;
      sicak.omurSonu = sicak.mesgulSonu + bostaOmur;
    } else {
      kayit.push({ t, gecikme: soguk + hizmet, soguk: true });
      const mesgulSonu = t + soguk + hizmet;
      canli.push({ mesgulSonu, omurSonu: mesgulSonu + bostaOmur, olusma: t });
    }
  }
  for (const o of canli) araliklar.push([o.olusma, Math.min(o.omurSonu, SURE)]);
  return { kayit, araliklar };
}

// 3) Kenar calisma zamani: ayni ornek modeli, yuk dugumlere bolunur, veri uzaktadir.
function kenarCalismaZamani(varis, { dugum, ...ayar }) {
  const paylar = Array.from({ length: dugum }, () => []);
  varis.forEach((t, i) => paylar[i % dugum].push(t));
  const kayit = [], araliklar = [];
  for (const pay of paylar) {
    const s = istekBasina(pay, ayar);
    kayit.push(...s.kayit);
    araliklar.push(...s.araliklar);
  }
  return { kayit, araliklar };
}

const yuzdelik = (dizi, p) => {
  const s = [...dizi].sort((a, b) => a - b);
  return s.length === 0 ? 0 : s[Math.min(s.length - 1, Math.floor((p / 100) * s.length))];
};
const ortusme = (aralik, a, b) =>
  Math.max(0, Math.min(aralik[1], b) - Math.max(aralik[0], a));

function ozet({ kayit, araliklar }, a, b) {
  const dilim = kayit.filter((k) => k.t >= a && k.t < b);
  const ayrilmis = araliklar.reduce((s, ar) => s + ortusme(ar, a, b), 0) / 1000;
  const kullanilan = (dilim.length * HIZMET) / 1000;
  return {
    istek: dilim.length,
    p50: yuzdelik(dilim.map((k) => k.gecikme), 50),
    p95: yuzdelik(dilim.map((k) => k.gecikme), 95),
    p99: yuzdelik(dilim.map((k) => k.gecikme), 99),
    soguk: (100 * dilim.filter((k) => k.soguk).length) / dilim.length,
    ayrilmis,
    kullanim: (100 * kullanilan) / ayrilmis,
  };
}

const varis = varislar();
console.log("varis izi: " + varis.length.toLocaleString("tr-TR") + " istek, " +
  SURE / 1000 + " s, isin kendisi " + HIZMET + " ms");
for (const [ad, a, b, hiz] of PENCERE)
  console.log("  " + ad.padEnd(12) + (a / 1000) + "-" + (b / 1000) + " s   " + hiz + " istek/s");

const MODEL = [
  ["uzun omurlu surec (75 yuva)", uzunOmurlu(varis, { yuva: 75, hizmet: HIZMET })],
  ["istek basina ornek", istekBasina(varis, { hizmet: HIZMET, soguk: 350, bostaOmur: 60_000 })],
  ["kenar calisma zamani (40 dugum)",
   kenarCalismaZamani(varis, { dugum: 40, hizmet: HIZMET + 60, soguk: 40, bostaOmur: 5_000 })],
];

console.log("\n" + "pencere".padEnd(12) + "model".padEnd(33) + "istek".padStart(7) +
  "p50".padStart(6) + "p95".padStart(6) + "p99".padStart(6) + "soguk".padStart(8) +
  "ayrilmis ornek-s".padStart(18) + "kullanim".padStart(10));
for (const [ad, a, b] of PENCERE) {
  for (const [mad, s] of MODEL) {
    const o = ozet(s, a, b);
    console.log(ad.padEnd(12) + mad.padEnd(33) + String(o.istek).padStart(7) +
      o.p50.toFixed(0).padStart(6) + o.p95.toFixed(0).padStart(6) +
      o.p99.toFixed(0).padStart(6) + o.soguk.toFixed(1).padStart(7) + "%" +
      o.ayrilmis.toFixed(0).padStart(18) + o.kullanim.toFixed(1).padStart(9) + "%");
  }
}
```

```
$ node calisma-zamani.mjs
varis izi: 29.655 istek, 600 s, isin kendisi 120 ms
  seyrek      0-200 s   0.5 istek/s
  duzenli     200-400 s   60 istek/s
  patlama     400-410 s   600 istek/s
  toparlanma  410-600 s   60 istek/s

pencere     model                              istek   p50   p95   p99   soguk  ayrilmis ornek-s  kullanim
seyrek      uzun omurlu surec (75 yuva)           87   120   120   120    0.0%             15000      0.1%
seyrek      istek basina ornek                    87   120   120   470    3.4%               354      2.9%
seyrek      kenar calisma zamani (40 dugum)       87   220   220   220  100.0%               446      2.3%
duzenli     uzun omurlu surec (75 yuva)        12010   120   120   120    0.0%             15000      9.6%
duzenli     istek basina ornek                 12010   120   120   120    0.2%              4133     34.9%
duzenli     kenar calisma zamani (40 dugum)    12010   180   180   180    0.3%              7968     18.1%
patlama     uzun omurlu surec (75 yuva)         5947   123   208   235    0.0%               750     95.2%
patlama     istek basina ornek                  5947   120   120   470    3.4%              2159     33.0%
patlama     kenar calisma zamani (40 dugum)     5947   180   180   220    2.0%              1488     48.0%
toparlanma  uzun omurlu surec (75 yuva)        11611   120   120   120    0.0%             14250      9.8%
toparlanma  istek basina ornek                 11611   120   120   120    0.0%             14601      9.5%
toparlanma  kenar calisma zamani (40 dugum)    11611   180   180   180    0.0%              8197     17.0%
```

Tablo, hiçbir biçimin bütün pencerelerde üstün olmadığını gösterir.

**Seyrek pencere ayrılmış kapasiteyi cezalandırır.** Seksen yedi istek için uzun ömürlü
süreç on beş bin örnek-saniye ayırır ve bunun binde birini kullanır. İstek başına örnek aynı
yükü üç yüz elli dört örnek-saniyeyle karşılar — kırk kat az. Kenar çalışma zamanı bu pencerede
her isteği soğuk başlatır, ama ödediği kalem kırk milisaniyedir.

**Patlama penceresi ayrılmış kapasiteyi haklı çıkarır.** Uzun ömürlü sürecin kullanımı yüzde
95'e çıkar; kapasite tam kullanılmıştır. Ama sınıra dayanmanın bedeli kuyruktur: p50 123
milisaniyede kalırken p95 208, p99 235 milisaniyeye çıkar. Bu artış işin uzamasından değil,
isteğin sırasını beklemesinden gelir. İstek başına örnek aynı patlamada p50'yi hiç
bozmaz — kuyruk yoktur, örnek sayısı talebi izler.

**Soğuk başlatma orta değerlerde görünmez.** Patlama penceresinde istek başına örnek
modelinin soğuk başlatma oranı yüzde 3,4'tür; p50 ve p95 bunu hiç göstermez, p99 470
milisaniye olarak gösterir. Ölçüyü ortalamadan okuyan biri soğuk başlatmayı hiç fark etmez.
Kuyruk ve soğuk başlatma, ancak üst yüzdeliklerde ayırt edilebilir.

**Toparlanma penceresi boşta bekleme süresinin bedelini gösterir.** Patlama bittikten sonra
istek başına örnek modelinin ayrılmış kapasitesi on dört bin altı yüz örnek-saniyeye çıkar
ve kullanımı yüzde 9,5'e düşer — uzun ömürlü sürecin yüzde 9,8'inin altına. Neden, patlamada
açılan yüzlerce örneğin boşta bekleme süresi boyunca ayakta kalmasıdır. Talebi izleyen kapasite,
talebi bir gecikmeyle izler.

**Kenar çalışma zamanının bedeli her satırda ödenir.** p50 değeri yüklü pencerelerde 180,
seyrek pencerede 220 milisaniyedir; ilk sayı veri deposuna olan altmış milisaniyelik
mesafenin her istekte ödenmesinden, ikincisindeki kırk milisaniyelik fark ise seyrek yükte
her isteğin soğuk başlatmaya düşmesinden gelir. Kenarın yakınlıktan gelen kazancı bu tabloda
yoktur; tablo yalnız sunucu tarafındaki davranışı ölçer. Kalemlerin toplamı,
Kenar Oluşturma dersindeki kuralı tekrarlar: kenar, verisi de kenara taşınabildiği ölçüde
kazandırır.

## Durumun Nerede Durduğu

Bellekte tutulan durum yalnız uzun ömürlü süreçte anlamlıdır ve orada da koşullu olarak
anlamlıdır. Örnek sayısı birden büyükse iki istek iki ayrı örneğe düşebilir; bir örnekte
tutulan oturum, sayaç ya da önbellek ötekinde yoktur.

Bunun üç sonucu vardır. **Oturum durumu paylaşılan bir depoda tutulur** ya da istemcinin
taşıdığı imzalı bir değerde durur; Uygulama Mimarisi kursundaki belirteç saklama kararı bu
noktada dağıtım kararıyla birleşir. **Oran sınırı ve kuyruk sayaçları paylaşılan depoya
taşınır**; örnek başına sayılan bir sınır, örnek sayısıyla çarpılan bir sınırdır. **Bağlantı
havuzu örnek başınadır**; veri deposunun bağlantı sınırı, örnek sayısı ile havuz boyutunun
çarpımına göre belirlenir. İstek başına örnek modelinde bu çarpım patlama sırasında hızla
büyür ve deponun sınırına ilk çarpan kalem genellikle burasıdır.

Aynı kullanıcıyı hep aynı örneğe yönlendirmek — yapışkan atama — durumu bellekte tutmayı
sürdürmenin yolu gibi görünür. Bir bedeli vardır: örnek söndüğünde o kullanıcının durumu
kaybolur ve yük dağılımı bozulur. Durumu paylaşılan depoya taşımak bu iki sorunu da doğurmaz.

## Hazırlık Ucu ve Zarif Kapanma

Sunucu gerektiren dağıtımın statik barındırmada karşılığı olmayan bir sorunu vardır: yayın,
çalışan bir süreci durdurmayı gerektirir. Süreç durdurulurken elindeki istekler yarıda
kalırsa, kullanıcı yayının olduğunu bir hata olarak görür.

Doğru kapanma sırası dört adımdır: hazırlık ucunun olumsuza dönmesi, yönlendiricinin bunu
fark etmesi için bir pay beklenmesi, dinleyicinin kapatılması ve açık isteklerin bitmesinin
beklenmesi.

```js
// zarif-kapanma.mjs — uzun omurlu surecin kapanma sirasi.
// 1) hazirlik ucu olumsuza doner, 2) yonlendiricinin fark etmesi icin beklenir,
// 3) dinleyici kapanir, 4) acik istekler bitince surecten cikilir.
import { createServer } from "node:http";

const IS_SURESI = 1500;    // ms, arsiv yaziminin surdugu sure
const HAZIRLIK_PAYI = 600; // ms, hazirlik ucu ile dinleyici kapanisi arasi

let hazir = true;
let acikIstek = 0;

const sunucu = createServer(async (istek, yanit) => {
  yanit.sendDate = false;
  if (istek.url === "/hazirlik") {
    yanit.writeHead(hazir ? 200 : 503, { "Content-Type": "text/plain" })
      .end(hazir ? "hazir\n" : "kapaniyor\n");
    return;
  }
  acikIstek += 1;
  await new Promise((c) => setTimeout(c, IS_SURESI));
  acikIstek -= 1;
  yanit.writeHead(200, { "Content-Type": "text/plain" }).end("arsivlendi\n");
});

sunucu.listen(8182, "127.0.0.1", () => console.log("sunucu  : dinleniyor"));

process.on("SIGTERM", () => {
  hazir = false;
  console.log("sunucu  : SIGTERM alindi, hazirlik olumsuza dondu, acik istek " + acikIstek);
  setTimeout(() => {
    sunucu.close(() => {
      console.log("sunucu  : acik istek " + acikIstek + ", surecten cikiliyor");
      process.exit(0);
    });
    console.log("sunucu  : dinleyici kapatildi, yeni baglanti alinmiyor");
  }, HAZIRLIK_PAYI);
});
```

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

```bash
#!/usr/bin/env bash
# Kapanma sirasini olcer: acik istek biter, yeni baglanti alinmaz.
node zarif-kapanma.mjs &
sunucu=$!
sleep 0.5

curl -sS -o /dev/null \
  -w 'istemci : surmekte olan istek durum %{http_code}, sure %{time_total} s\n' \
  http://127.0.0.1:8182/arsiv &
yavas=$!
sleep 0.3

curl -sS -o /dev/null -w 'istemci : hazirlik ucu %{http_code} (SIGTERM oncesi)\n' \
  http://127.0.0.1:8182/hazirlik
kill -TERM "$sunucu"
sleep 0.3
curl -sS -o /dev/null -w 'istemci : hazirlik ucu %{http_code} (SIGTERM sonrasi)\n' \
  http://127.0.0.1:8182/hazirlik

sleep 0.6
if curl -sS -o /dev/null http://127.0.0.1:8182/arsiv 2> /dev/null; then
  echo "istemci : yeni istek kabul edildi"
else
  echo "istemci : yeni istek baglanamadi, curl cikis kodu $?"
fi

wait "$yavas"
wait "$sunucu"
```

```
sunucu  : dinleniyor
istemci : hazirlik ucu 200 (SIGTERM oncesi)
sunucu  : SIGTERM alindi, hazirlik olumsuza dondu, acik istek 1
istemci : hazirlik ucu 503 (SIGTERM sonrasi)
sunucu  : dinleyici kapatildi, yeni baglanti alinmiyor
istemci : yeni istek baglanamadi, curl cikis kodu 7
istemci : surmekte olan istek durum 200, sure 1.504674 s
sunucu  : acik istek 0, surecten cikiliyor
```

Sürelerin tamamı ortama bağlıdır; belirleyici olan sıradır. Kapanma sinyali geldiğinde
elde bir açık istek vardır; o istek `200` ile ve tam süresinde tamamlanır. Sinyalden sonra
hazırlık ucu `503` döner ama bağlantı noktası hâlâ açıktır — bu pay, yönlendiricinin bu
örneği listeden çıkarması için bırakılmıştır. Pay dolduğunda dinleyici kapanır ve yeni
bağlantı kurulamaz; süreçten çıkış ise açık isteğin bitmesini bekler.

Payın atlanması iki yanlıştan birine yol açar. Dinleyici hemen kapatılırsa, yönlendirici
henüz haberi olmadığı için bu örneğe istek göndermeye devam eder ve o istekler bağlantı
hatası alır. Hazırlık ucu hiç kullanılmazsa, aynı sonuç kapanmanın ilk milisaniyesinden
itibaren oluşur. İstek başına örnek ve kenar biçimlerinde bu sıra platformun sorumluluğundadır,
ama açık isteğin yarıda kesilmemesi için işin süresi platformun tanıdığı süreden kısa
olmalıdır.

## Seçim Kuralı

Karar üç ölçüye bağlanır: yükün düzenliliği, işin süresi ve verinin konumu.

Yük düzenliyse ve boşta kalan pencere yoksa uzun ömürlü süreç seçilir; ayrılmış kapasitenin
kullanımı yüksektir, soğuk başlatma yoktur, bağlantı havuzu ve bellek içi önbellek kullanılır.
Yük seyrek ya da ani patlamalıysa istek başına örnek seçilir; ayrılmış kapasite talebi izler,
karşılığı üst yüzdeliklerde görünen soğuk başlatmadır. İş kısa, veriye bağımlılığı az ve
coğrafi yakınlık belirleyiciyse kenar çalışma zamanı seçilir.

Bu kural tek bir seçim yapılacağı anlamına gelmez. Kuzey Yamaç sitesinde
statik barındırma sayfaları, uzun ömürlü bir süreç arşiv yazma ucunu, kenar çalışma zamanı da
yönlendirme ve başlık ekleme işlerini üstlenebilir. Ayrım işin kendisine göre yapılır.

## Özet

- Üç barındırma biçimi ayrılmış kapasite, soğuk başlatma, eşzamanlılık ve durum tutma
  eksenlerinde ayrılır; hiçbiri bütün yük pencerelerinde üstün değildir.
- Seyrek yükte uzun ömürlü süreç ayırdığı kapasitenin binde birini kullanır; istek başına
  örnek aynı yükü kırk kat az kapasiteyle karşılar.
- Patlamada uzun ömürlü süreç kapasitesini tam kullanır ama kuyruk oluşur: p50 sabit
  kalırken p99 yükselir. İstek başına örnek kuyruk üretmez, soğuk başlatma üretir.
- Soğuk başlatma ve kuyruk orta değerlerde görünmez; ölçü üst yüzdeliklerden okunur.
- Bellekte durum yalnız tek örnekte güvenlidir; oturum, sayaç ve önbellek paylaşılan depoya
  taşınır, bağlantı havuzu ise örnek sayısıyla çarpılır.
- Zarif kapanma dört adımdır: hazırlık ucu olumsuza döner, pay beklenir, dinleyici kapanır,
  açık istekler biter. Pay atlanırsa yönlendirici hâlâ istek gönderir ve o istekler düşer.

## Sonraki Adım

Buraya kadar iki dağıtım biçimi ve bir kapanma sırası kuruldu; hepsi tek bir hedefe, yayına
bakıyordu. Oysa bir değişikliğin yayına girmeden önce çalıştığının görülmesi gerekir ve
Geliştirme Sunucusu dersinin son cümlesi bunun nedenini vermişti: geliştirme kipinde çalışması,
yayın kipinde çalıştığının kanıtı değildir. Sonraki ders her değişiklik için ayrı bir ortam
kurar: kendi adresi olan, yayın kipiyle derlenmiş, yayın verisine dokunmayan ve dizinlenmeyen
bir dağıtım. Bu ortamların kimliği, beşinci dersteki belirlenimci adlandırmadan türetilir.
