---
title: 'Kapasite Planlama'
source: 'https://academia.sh/tr/kurslar/backend-uretim/kapasite-planlama'
course: 'Sunucu Güvenliği ve Üretime Alma'
language: tr
updated: '2026-08-17T18:06:49+00:00'
license: 'CC BY-SA 4.0'
---

# Kapasite Planlama

Ölçülen yükten süreç ve düğüm sayısına giden hesap: tek sürecin havuz boyuna göre ölçülen kapasitesi, buradan çıkan süreç, bağlantı ve düğüm sayısı, depo bağlantı sınırının havuz boyunu geriye doğru belirlemesi ve az ile çok tahminin hedef yükte hiç görünmeyip yığılmada ürettiği fark.

Bu konu boyunca sayılan her şey — düşen istek, kesinti saniyesi, geri alma adımı — kaynağın
verili olduğu bir düzende ölçüldü; düğümler, yayında ikiye katlanan süreçler ve göçün koştuğu
depo hep vardı. Bu ders o düzeni kuran sayıyı üretir: bir süreç hangi yükü
taşır, kaç süreç gerekir, yayın ve arıza payı ne ekler, kaç düğüm eder.

Yük testinin yöntemi **Başarım Karşıt Kalıpları ve İzleme**, kapasite sınırının sınamayla
bulunması **İşlevsel Olmayan Test** kursunda kuruldu; burada o ölçüm girdidir. Kursun kuralı
sürer: yanlış tahmin hata vermez, ölçü farkı gösterir.

- **DP19.** Hedef yük saniyede 150 istektir; yığılmada dört katı gelir.
- **DP20.** Depo eş zamanlı 16 bağlantı kabul eder, üstündeki yuva okunmadan kapatılır.
- **DP21.** Bir düğümde uygulamaya 256 MiB ayrılır.

## Ölçülen Düzenek

Depo bağlantı sınırını gerçekten uygular.

```js
// depo.mjs — odunc kaydini veren depo; es zamanli acik baglanti sayisi SINIR ile kisitlidir
import { createServer } from 'node:http';

const { SINIR = 16, GECIKME = 12, PORT = 8830 } = process.env;   // plan.mjs bunlari gecer
let acik = 0, enYuksek = 0;

const depo = createServer((istek, yanit) => {
  if (istek.url === '/olcum') return yanit.end(JSON.stringify({ enYuksek }));
  setTimeout(() => yanit.end('{"kayit":1}'), Number(GECIKME));
});
depo.on('connection', (yuva) => {          // sinirin ustundeki yuva okunmadan kapatilir
  if (acik >= Number(SINIR)) return yuva.destroy();
  acik += 1;
  enYuksek = Math.max(enYuksek, acik);
  yuva.on('close', () => { acik -= 1; });
});
depo.listen(Number(PORT), () => console.log('depo hazir'));
```

Ödünç ucunda havuz hem depo yuvasını hem çalışma tamponunu tutar; istek başına iş sabittir.

```js
// servis.mjs — odunc ucunun bir kopyasi; HAVUZ yuva ve HAVUZ tampon bastan ayrilir
import { createServer, Agent, get } from 'node:http';
import { createHash } from 'node:crypto';

const { HAVUZ = 2, KUYRUK = 32, TUR = 40000, TAMPON = 4194304, DEPO = 8830,
  PORT = 8831 } = process.env;                    // plan.mjs bunlari gecer
const havuz = Number(HAVUZ), tur = Number(TUR);
const baglantilar = new Agent({ keepAlive: true, maxSockets: havuz });
const tamponlar = Array.from({ length: havuz }, () => Buffer.allocUnsafe(Number(TAMPON)).fill(0x2d));
const bos = tamponlar.map((_, i) => i);
const bekleyen = [];
let enUzunKuyruk = 0;

function al() {                     // bos is yeri yoksa kuyruga gir, kuyruk da doluysa -1
  if (bos.length) return Promise.resolve(bos.pop());
  if (bekleyen.length >= Number(KUYRUK)) return Promise.resolve(-1);
  enUzunKuyruk = Math.max(enUzunKuyruk, bekleyen.length + 1);
  return new Promise((c) => bekleyen.push(c));
}
const birak = (y) => { const s = bekleyen.shift(); if (s) s(y); else bos.push(y); };
const depoSorgu = () => new Promise((c, r) => get({ port: Number(DEPO), path: '/kayit',
  agent: baglantilar }, (y) => { y.resume(); y.on('end', c); }).on('error', r));

function isle(no, yer) {            // istek basina sabit is: tur kadar ozet turu
  let ozet = createHash('sha256').update(String(no)).digest();
  for (let i = 0; i < tur; i += 1) ozet = createHash('sha256').update(ozet).digest();
  tamponlar[yer].write(ozet.toString('hex'));
  return tamponlar[yer].subarray(0, 8).toString('hex');
}

createServer(async (istek, yanit) => {
  if (istek.url === '/olcum') {
    return yanit.end(JSON.stringify({ enUzunKuyruk, rss: process.memoryUsage().rss }));
  }
  const yer = await al();
  if (yer < 0) return yanit.writeHead(503).end('{"durum":"kuyruk dolu"}');
  try {
    await depoSorgu();
    yanit.end(JSON.stringify({ damga: isle(istek.url, yer) }));
  } catch (e) {
    yanit.writeHead(502).end(JSON.stringify({ hata: e.code ?? e.message }));
  } finally { birak(yer); }
}).listen(Number(PORT), () => console.log('servis hazir'));
```

## Ölçümden Tahmine

Sürücü tek süreci havuz boyunu değiştirerek doyurur, kapasiteden süreç ve düğüm sayısını
hesaplar, üç tahmini aynı yük ve yığılma altında koşturur. 40.000 özet turu, 4 MiB tampon ve
depo sınırı koşumdan bağımsızdır; hız ve bellek bu koşumundur.

```js
// plan.mjs — tek surecin kapasitesi havuz basina olculur, surec ve dugum sayisi hesaplanir,
// uc tahmin ayni hedef yuk ve ayni yigilma altinda kosturulur
import { spawn } from 'node:child_process';

const HEDEF = 150, YIGILMA = 4;             // DP: saniyede gelen istek ve yigilma kati
const SURE = 1800, YSURE = 1000;            // olcum ve yigilma sureleri (ms)
const TUR = 40000, TAMPON = 4 * 1024 * 1024, KUYRUK = 32;
const DEPO_SINIR = 16, DEPO_GECIKME = 12;   // DP: deponun kabul ettigi es zamanli baglanti
const DUGUM_BELLEGI = 256, PAY = 2;         // DP: dugum bellegi (MiB); yayin + ariza payi

let taban = 8830;
const cocuklar = [];
const baslat = (dosya, env) => new Promise((k, r) => {
  const c = spawn(process.execPath, [dosya], { stdio: ['ignore', 'pipe', 'inherit'], env: { ...process.env, ...env } });
  cocuklar.push(c);
  c.stdout.once('data', k);
  c.once('exit', (kod) => r(new Error(`${dosya} ${kod} ile cikti`)));
});
const kapat = () => { cocuklar.forEach((c) => c.kill('SIGKILL')); cocuklar.length = 0; };

async function kur(surec, havuz) {
  const depo = taban;
  taban += 20;
  await baslat('depo.mjs', { PORT: depo, SINIR: DEPO_SINIR, GECIKME: DEPO_GECIKME });
  const portlar = [];
  for (let i = 1; i <= surec; i += 1) {
    await baslat('servis.mjs', { PORT: depo + i, DEPO: depo, HAVUZ: havuz, KUYRUK, TUR, TAMPON });
    portlar.push(depo + i);
  }
  return { depo, portlar };
}
const olcum = (p) => fetch(`http://127.0.0.1:${p}/olcum`).then((y) => y.json());
const iste = (p, i) => fetch(`http://127.0.0.1:${p}/odunc/${i}`)
  .then((y) => { y.body.cancel().catch(() => {}); return y.status; }).catch(() => 0);
function tablo(bas, satirlar) {
  const g = bas.map((b, i) => Math.max(b.length, ...satirlar.map((s) => String(s[i]).length)));
  for (const r of [bas, ...satirlar]) console.log(r.map((v, i) => String(v).padEnd(g[i])).join('  ').trimEnd());
}

// acik dongu: sabit hizda gonderilir, yanit kodlari sayilir
async function dene(surec, havuz, hiz, sure) {
  const { depo, portlar } = await kur(surec, havuz);
  const say = { tamam: 0, kuyruk: 0, kopan: 0 }, ucusta = [];
  let borc = 0, n = 0;
  for (let t = 0; t < sure; t += 20) {
    for (borc += (hiz * 20) / 1000; borc >= 1; borc -= 1) {
      n += 1;
      ucusta.push(iste(portlar[n % portlar.length], n)
        .then((k) => { say[k === 200 ? 'tamam' : k === 503 ? 'kuyruk' : 'kopan'] += 1; }));
    }
    await new Promise((k) => setTimeout(k, 20));
  }
  await Promise.all(ucusta);
  const ic = await Promise.all(portlar.map((x) => olcum(x)));
  cocuklar.slice(1).forEach((c) => c.kill('SIGKILL'));   // depo olcumu bir baglanti ister
  await new Promise((k) => setTimeout(k, 150));
  const d = await olcum(depo);
  kapat();
  return [say.tamam, say.kuyruk, say.kopan, Math.max(...ic.map((x) => x.enUzunKuyruk)),
    d.enYuksek, (ic.reduce((t, x) => t + x.rss, 0) / 2 ** 20).toFixed(0)];
}

// 1. asama: kapali dongu; istemci 16 istek ucusta tutar, sinirlayan sey havuzdur
const plan = [];
for (const h of [1, 2, 4, 8]) {
  const { depo, portlar } = await kur(1, h);
  const bit = Date.now() + SURE;
  let n = 0;
  await Promise.all(Array.from({ length: 16 }, async () => {
    while (Date.now() < bit) if (await iste(portlar[0], n) === 200) n += 1;
  }));
  const { rss } = await olcum(portlar[0]);
  const { enYuksek } = await olcum(depo);
  kapat();
  const hiz = n / (SURE / 1000), yuk = Math.ceil(HEDEF / hiz);
  plan.push({ h, hiz, mib: rss / 2 ** 20, yuva: enYuksek, yuk, surec: yuk + PAY, baglanti: (yuk + PAY) * h });
}
tablo(['havuz', 'tamamlanan/sn', 'depo yuvasi', 'rss (MiB)', 'yuku karsilayan surec', '+pay',
  'toplam baglanti', 'depo siniri'],
  plan.map((p) => [p.h, p.hiz.toFixed(1), p.yuva, p.mib.toFixed(0), p.yuk, p.surec, p.baglanti,
    p.baglanti <= DEPO_SINIR ? 'gecer' : 'asilir']));
const sec = plan.filter((p) => p.baglanti <= DEPO_SINIR).sort((a, b) => a.surec - b.surec)[0];
const dBasina = Math.floor(DUGUM_BELLEGI / sec.mib);
console.log(`\nsecilen plan: havuz ${sec.h}, ${sec.surec} surec (${sec.yuk} yuk + ${PAY} pay), `
  + `${sec.baglanti} baglanti, ${Math.ceil(sec.surec / dBasina)} dugum (dugume ${dBasina} surec)`);

// 2. asama: uc tahmin, once hedef yuk sonra yigilma
const ayarlar = [['az tahmin', sec.yuk - 1, sec.h], ['secilen plan', sec.surec, sec.h],
  ['cok tahmin, havuz dokunulmamis', sec.surec + 2, 4]];
for (const [ad, hiz, sure] of [['hedef yuk', HEDEF, SURE], ['yigilma', HEDEF * YIGILMA, YSURE]]) {
  const satirlar = [];
  for (const [etiket, surec, havuz] of ayarlar) {
    satirlar.push([etiket, surec, havuz, surec * havuz, ...await dene(surec, havuz, hiz, sure)]);
  }
  console.log(`\n${ad} — ${hiz} istek/sn`);
  tablo(['ayar', 'surec', 'havuz', 'havuz carpimi', '200', '503', '502', 'en uzun kuyruk',
    'depo yuvasi', 'rss'], satirlar);
}
```

```
havuz  tamamlanan/sn  depo yuvasi  rss (MiB)  yuku karsilayan surec  +pay  toplam baglanti  depo siniri
1      41.7           2            83         4                      6     6                gecer
2      69.4           3            90         3                      5     10               gecer
4      68.9           5            98         3                      5     20               asilir
8      70.6           9            112        3                      5     40               asilir

secilen plan: havuz 2, 5 surec (3 yuk + 2 pay), 10 baglanti, 3 dugum (dugume 2 surec)

hedef yuk — 150 istek/sn
ayar                            surec  havuz  havuz carpimi  200  503  502  en uzun kuyruk  depo yuvasi  rss
az tahmin                       2      2      4              270  0    0    23              4            181
secilen plan                    5      2      10             270  0    0    0               6            449
cok tahmin, havuz dokunulmamis  7      4      28             270  0    0    0               7            642

yigilma — 600 istek/sn
ayar                            surec  havuz  havuz carpimi  200  503  502  en uzun kuyruk  depo yuvasi  rss
az tahmin                       2      2      4              279  321  0    32              4            183
secilen plan                    5      2      10             460  140  0    32              10           520
cok tahmin, havuz dokunulmamis  7      4      28             351  0    249  17              16           683
```

## Havuzun Üç Faturası

Havuz bir iken süreç saniyede 41,7 istek tamamladı; ikide 69,4'e sıçradı, dört ve sekizde aynı
bantta kaldı. Havuz bir iken depo beklemesi hiçbir işle örtüşemez, ikide bir istek beklerken
diğeri işlenir. İkinin üstünde örtüşecek bekleme kalmaz.

Sonraki iki sütun ayarın fiyatıdır: depoda açılan yuva 2, 3, 5 ve 9'a, süreç belleği 83'ten
112 MiB'a çıktı. Havuz bir üst sınır değil, doyumda gerçekleşen bağlantı sayısıdır.

## Süreçten Düğüme

Havuz iki iken 150 isteği karşılamak için `tavan(150 / 69,4) = 3` süreç yeter; yayın ve arıza
payı eklenince beş olur. Beş süreç havuz iki ile depoya on bağlantı düşürür. Havuz dört
seçilseydi süreç sayısı yine beş olurdu ama bağlantı yirmiye, havuz sekizde kırka çıkardı.

Bu, hesabın yönünü tersine çevirir: **depo sınırı bölü süreç sayısı** havuza tavan koyar, tavan
kapasiteyi, kapasite de süreç sayısını belirler.

Düğüm sayısı bir bölmedir: 90 MiB'lik süreç 256 MiB'lik düğüme ikişer sığar, beş süreç üç düğüm
eder. Burada bir kayma var — **pay süreç cinsinden hesaplandı, arıza düğüm cinsinden gelir**:
bir düğüm gidince iki süreç birden gider.

## İki Yönlü Yanlış Tahmin

Hedef yükte üç ayar da aynı görünüyor: 270 isteğin 270'i tamamlandı, üçünde de hata sıfır.
Yanlış tahminin sessizliği burasıdır.

Az tahminin izi tek sütunda: iki süreçle en uzun kuyruk 23'e çıktı, doğru planda sıfır kaldı.
İki süreç saniyede yaklaşık 139 istek taşır, hedef 150'dir; biriken istek kuyruğu birkaç
saniyede doldurur, ölçüm penceresi bundan kısadır. Yığılmada aynı ayar 321 istek kaybetti. Kuyruk derinliği, düşen istekten önce gelen ve tek başına hiçbir
hata üretmeyen göstergedir.

Çok tahminin hedef yükteki tek izi bellektedir: yedi süreç 642 MiB, beş süreç 449 MiB tuttu.
Yığılmada yedi süreç depoya yirmi sekiz bağlantı istedi; depo yuvası on altıda doydu ve 249
istek 502 aldı. Tamamlanan 351 istek, doğru planın 460'ından **azdır**. Doğru plan taşıyamadığı
140 isteği kendi kuyruğunda 503 ile reddetti; çok tahmin paylaşılan kaynağı harcadı.

Üç girdi üç ayrı katmanda durur: süreç sayısı süreç yöneticisinde, havuz uygulamanın ortamında,
bağlantı sınırı depoda. Ölçülen şey ilk ikisinin çarpımıdır ve hiçbir dosyada yazmaz.

## Özet

- Havuz boyu kapasiteyi (41,7'den 69,4 isteğe), süreç belleğini (83'ten 112 MiB'a) ve depoya
  düşen yuva sayısını (2'den 9'a) birden belirler; ikinin üstünde yalnız fiyat arttı.
- Ölçümden plana giden hesap üç adımdır — yükü karşılayan süreç, yayın ve arıza payı, bellekle
  bölünen düğüm: havuz 2, 5 süreç, 10 bağlantı, 3 düğüm.
- Depo bağlantı sınırı havuza tavan koyar: aynı süreç sayısıyla havuz 4 yirmi, havuz 8 kırk
  bağlantı ederdi.
- Pay süreç cinsinden hesaplanırken arıza düğüm cinsinden gelir; düğüme iki süreç sığdığı için
  bir düğümün kaybı, tek süreçlik arıza payının iki katıdır.
- Hedef yükte üç ayar da 270 isteğin 270'ini karşıladı; az tahminin izi 23'e çıkan kuyruk, çok
  tahminin izi boşta duran 193 MiB oldu. Yığılmada az tahmin 321 isteği reddetti, çok tahmin
  depo yuvası dolduğu için 249 istek kopardı.

## Kurs Kapanışı

| Ders | Doğru ayarın ölçüsü | Yanlış ayarın sessiz sonucu | Ayarın yeri |
|---|---|---|---|
| Girdi Doğrulama | İzin listesinde 0 ve 1, engellemede 11 ve 4 yanlış | Üç yanlış ayarda hata 0 | Uçta 0, depoda 22 boşa adım |
| Enjeksiyon Sınıfı | Ayrı işlenen yolunda bozulma 0 | Kaçan birleştirme 10 girdinin 4'ünde sapıyor | Karar 12 çağrı yerinde ayrı |
| Kaynaklar Arası Erişim | Köken listesi 2 dış kökene açık | Joker ayar 200 döndürdü, istemci attı | 5 uçta ayrı, tek katmanda 1 |
| Güvenlik Başlıkları | Tek katmanda 1 kayıt noktası, yeni uç için 0 satır | Tek yanlış değer 10/10'u 0/10'a düşürdü | Uç başına 10 dosya, tek katmanda 1 |
| Gizli Değer Yönetimi | Pencere 390 saniye; penceresiz döndürme 36 ret | Sızan anahtar 900. saniyede 200 aldı | Anahtar 14 yerde yılda 56 adım |
| Bağımlılık Riski | Günlük yükseltme 113 açık gün, 237 müdahale günü | Gevşek aralıkta iki dağıtım 14 pakette ayrıştı | Sürüm aralığı bildirimde |
| Denetim Kaydı | Bütün karar noktaları 8 sorunun 8'ini yanıtladı | Son 25 kaydın silinmesi yakalanmadı | Çapa dönemi: çapasız 3.012, 500'de birle 499 |
| Kötüye Kullanım | Katmanlı anahtar 2.446 istek durdurdu, yanlış kalma 0 | Normalize edilmeyince durdurulan 2.266'ya indi | Anahtar seçimi sınırlayıcıda |
| Ters Vekil | Aktarım açıkken 16 isteğin 11'i geçti, kayıtta 4 kimlik | Kapalıyken 6 iyi istek durduruldu | Aktarım vekilde, gövde sınırı iki katmanda |
| Süreç Yöneticileri | Anında başlatma 24 isteğin 20'sini yanıtladı; 500 ms bekleme 6 isteği boşalttı | Başlamayan süreçte onlarca yeniden başlatma (o koşumda 43) | Politika ve bekleme süreç yöneticisinde |
| Yatay/Dikey Ölçekleme | Havuz ikiye inince 60 isteğin 60'ı yanıtlandı | Havuza dokunulmayınca bağlantı 32'ye çıktı, 30 istek yanıtsız | Süreç sayısı ve havuz ayrı |
| Durumsuz Uygulama | Tek kopyada 21 isteğin 21'i doğru | İki kopyada 12 istek yanlışlandı, kod değişmedi | 55 satırda 12 çağrı yeri |
| Oturum ve Yapışkanlık | Paylaşılan depoda kaybolan oturum 0 | Süreç belleğinde 8 ekleme biriktirmedi, hepsi 200 döndü | İmza anahtarı düğüm başına |
| Sıfır Kesintili Yayın | Mavi–yeşil ve aşamalı yayın 0 istek düşürdü | Sert kapanmada uçuştaki 8 istek düştü, sayaçta görünmedi | Yayın düzeni dağıtımda |
| Göç ile Yayın Sırası | Genişlet–daralt 120 isteğin 120'sini 5 adımda karşıladı | Çift yazma atlanınca alan boş kaldı, istek 200 döndü | Sıra yazılı listede |
| Kapasite Planlama | Havuz 2 ile 5 süreç, 10 bağlantı, 3 düğüm | Az tahminde kuyruk 23'e çıktı, 193 MiB boşta durdu | Süreç yöneticisi, uygulama ve depo |

Orta sütun kursun kuralını on altı kez yazıyor: **yanlış yapılandırma hata vermez; ölçü farkı
gösterir.** Eksik kalan başlık, kapatılmayan anahtar, atlanan çift yazma, fazla tutulan süreç —
hiçbiri istisna fırlatmadı. Doğruyu yanlıştan ayıran şey her derste sayılan bir fark oldu: geçen
istek, açılan köken, kurtarılamayan kayıt, boşta duran bellek. Her ayarın yanına ölçüsü de yazılır.

Bu ders **Sunucu Güvenliği ve Üretime Alma** kursunu ve müfredatı kapatıyor. Sunucu Tarafı
Temelleri isteğin sunucudaki yolunu, Web API Tasarımı sözleşmeyi, Kimlik ve Yetki erişimi, Veri
Erişim Katmanı kalıcılığı, Önbellekleme ve Eşzamansız İşleme isteğin dışına çıkan işi, Servis
Mimarileri sınırı, Gözlemlenebilirlik ve Güvenilirlik görünürlüğü kurdu; bu kurs da üretime alma
kararlarını. Sırada okurun kendi sistemi var: hangi ucun doğrulayıcısı eksik, kaç süreç koşuyor
ve o sayı hangi ölçümden çıktı.
