---
title: 'Görev Kuyrukları ve Arka Plan İşleri'
source: 'https://academia.sh/tr/kurslar/uygulama-katmani/gorev-kuyruklari-ve-arka-plan-isleri'
course: 'Uygulama Katmanı ve Servis Etkileşimi'
language: tr
updated: '2026-08-17T18:10:55+00:00'
license: 'CC BY-SA 4.0'
---

# Görev Kuyrukları ve Arka Plan İşleri

Uzun bir işin istek yolundan çıkarılmasının ölçülmesi: rapor işinin süresinin giriş kursunun sayılarından türetilmesi, aynı yuva havuzunu paylaşan kısa ve uzun işlerde kısa isteğin kuyruk kuyruğunun sayılması, ayrı bir görev kuyruğuna alındığında hangi ölçünün düzeldiği ve ölçekleme biriminin kopyadan işçiye geçmesi.

Önceki dersin bütün olayları birbirinin eşiydi: her durum olayı aynı büyüklükte, aynı işi yapan,
milisaniyeler süren bir kayıttı. Birikme hesabı da buna dayanıyordu — kapasite tek bir sayıyla
ifade edilebilir, çünkü işler tek tiptir. Aynı sistemde bu varsayımın tutmadığı bir iş var:
satıcının istediği dönem raporu binlerce gönderi kaydını tarar ve saniyelerce sürer. Böyle bir iş
isteğin içinde çalıştırıldığında yalnız kendi süresini harcamaz, arkasındaki kısa istekleri de
bekletir.

Bu ders o işi istek yolundan çıkarır. **Görev kuyruğu** (task queue) mesaj kuyruğunun aynı
mekaniğidir; ayrıldığı yer içeriğidir — kuyruğa yazılan şey bir olay bildirimi değil, birinin
yapılmasını istediği bir **iştir**. İşçi süreçleri, çekme tabanlı dağıtım, gözetim, zarif kapanma
ve uzun işin parçalara bölünüp ilerlemesinin yazılması Önbellekleme, Kuyruklar ve Eşzamansız
İşleme kursunda kuruldu; hiçbiri yeniden anlatılmaz. Burada ölçülen tek şey ayırmanın **kapasite
karşılığıdır**: kısa isteğin beklemesi ne kadar düzelir ve tasarımın ölçekleme birimi ne olur.

## İşin Boyu Nereden Geliyor

Uzun işin süresi uydurulmaz, K01'in sayılarından çıkar. Kabaca Büyüklük Hesabı dersi günde 4000
fatura satırı buluyordu ve her satır bir satıcının bir günüydü; satıcı sayısı 4000'dir. Günde
400.000 gönderi oluştuğuna göre satıcı başına günlük gönderi 100'dür. Ücretlendirme dönemi V11
gereği 30 gün olduğuna göre bir dönem raporu **3000 gönderi kaydı** tarar. Aynı ders tarama
hızını da veriyor: 833,33 kayıt/s, yani kayıt başına 1,20 ms. Rapor işi böylece **3,60 saniye**
sürer. Bu sayıların hepsi hesap sınıfındadır.

Karşılaştırılan kısa iş takip sorgusudur ve tek bir kayıt okur, yani bir tarama biriminde biter.
Aradaki oran doğrudan 3000'dir. Modelin tur birimi de buradan seçilmiştir: bir tur 1,20 ms'dir ve
model içindeki hiçbir süre ölçülmez, turdan çevrilir.

İki varsayım gerekir ve ikisi de bu kursun kendi varsayımıdır; K01'in tablosuna eklenmez.

**K2 — sabah penceresi: 30 dakika.** Gerekçe: K01'in V10 satırı "satıcı raporu sabah ister"
diyor; rapor talepleri iş gününün açılışına sıkışır.

**K3 — pencerede rapor isteyen satıcı oranı: 0,50.** Gerekçe: dönem raporu ayın belirli
günlerinde toplu olarak istenir ve o günlerde satıcıların yarısının uğradığı varsayılır.
Duyarlılığı aşağıdaki tabloda 0,25 satırlarıyla ölçülüyor.

Okuma yükü K01 ile K02'den gelir: tepe okuma 416,67 istek/s, kopya sayısı 4 — Trafik Katmanı
kursunun oturum yapışkanlığı dersi bu sayıyı 3'ten 4'e çıkarmıştı. Kopya başına düşen okuma
104,17 istek/s'dir.

## Aynı Havuzda İki İş

Düzenek tek bir kopyayı süreç içi bir modelle kurar. Kopyanın belirli sayıda **yuvası** vardır;
her yuva bir anda tek bir isteği tutar, boşalınca kuyruğun başındakini alır. Varışlar sabit
tohumlu iki bağımsız üreteçten gelir, dolayısıyla bütün tasarımlar **aynı** istek dizisiyle
karşılaşır. Model olduğu için sonuçlar belirlenimlidir ve makineden bağımsızdır.

```js
// gorev/havuz.mjs — uzun isin istek yolunda kalmasi ile gorev kuyruguna alinmasinin
// karsilastirilmasi. MODEL: tur = 1,20 ms (K01: toplu is tarama 833,33 kayit/s), varislar
// sabit tohumlu bir uretecten gelir. Sonuclar belirlenimlidir; sure olculmez, turden cevrilir.
const TUR_MS = 1.2;                // K01: kayit basina 1,20 ms
const OKUMA_TEPE = 416.67;         // K01: tepe okuma istek/s
const KOPYA = 4;                   // K02 oturum yapiskanligi dersi: 4 kopya
const SATICI = 4000;               // K01: gunluk fatura satiri = satici sayisi
const RAPOR_KAYIT = 3000;          // K01: satici basina 100 gonderi/gun x V11 = 30 gun
const K2_PENCERE_DK = 30;          // bu kursun varsayimi K2: sabah penceresi
const K3_ORAN = 0.5;               // bu kursun varsayimi K3: pencerede rapor isteyen satici orani
const TOHUM = 20260730;

const TUR = Math.round((K2_PENCERE_DK * 60 * 1000) / TUR_MS);
const takipP = (OKUMA_TEPE / KOPYA) * (TUR_MS / 1000);
const raporSayisi = (oran) => (SATICI * oran) / KOPYA;

function uretec(tohum) {           // splitmix32: iki akis icin bagimsiz varis dizisi
  let a = tohum >>> 0;
  return () => {
    a = (a + 0x9e3779b9) >>> 0;
    let z = Math.imul(a ^ (a >>> 16), 0x21f0aaad) >>> 0;
    z = Math.imul(z ^ (z >>> 15), 0x735a2d97) >>> 0;
    return ((z ^ (z >>> 15)) >>> 0) / 4294967296;
  };
}

function kosum({ yuva, ayri, isci, oran = K3_ORAN }) {
  const raporP = raporSayisi(oran) / TUR;
  const rastTakip = uretec(TOHUM), rastRapor = uretec(TOHUM + 1);
  const meshul = new Array(yuva).fill(0), raporMeshul = new Array(isci).fill(0);
  const kuyruk = [], gorev = [], bekleme = [], raporSure = [];
  let gelenRapor = 0;
  for (let t = 0; t < TUR; t += 1) {
    if (rastTakip() < takipP) kuyruk.push({ t, sure: 1 });
    if (rastRapor() < raporP) { gelenRapor += 1; (ayri ? gorev : kuyruk).push({ t, sure: RAPOR_KAYIT, rapor: true }); }
    for (let i = 0; i < yuva; i += 1) {
      if (meshul[i] > 0) meshul[i] -= 1;
      if (meshul[i] === 0 && kuyruk.length > 0) {
        const is = kuyruk.shift();
        if (is.rapor) raporSure.push(t - is.t + is.sure); else bekleme.push(t - is.t);
        meshul[i] = is.sure;
      }
    }
    for (let i = 0; i < isci; i += 1) {
      if (raporMeshul[i] > 0) raporMeshul[i] -= 1;
      if (raporMeshul[i] === 0 && gorev.length > 0) {
        const is = gorev.shift();
        raporSure.push(t - is.t + is.sure);
        raporMeshul[i] = is.sure;
      }
    }
  }
  const d = [...bekleme].sort((a, b) => a - b);
  const y = (p) => d[Math.min(d.length - 1, Math.floor((p / 100) * d.length))];
  return { takip: bekleme.length, p50: y(50), p99: y(99), enUzun: d[d.length - 1],
    geciken: bekleme.filter((b) => b * TUR_MS > 100).length,
    gelenRapor, biten: raporSure.length,
    raporOrt: raporSure.reduce((a, b) => a + b, 0) / raporSure.length };
}

console.log(`tur = ${TUR_MS} ms, pencere ${K2_PENCERE_DK} dk = ${TUR} tur, ${KOPYA} kopya`);
console.log(`kopya basina takip ${(OKUMA_TEPE / KOPYA).toFixed(2)} istek/s, ` +
  `K3 = ${K3_ORAN} -> kopya basina beklenen rapor ${raporSayisi(K3_ORAN)}`);
console.log(`rapor isi = ${RAPOR_KAYIT} kayit = ${(RAPOR_KAYIT * TUR_MS / 1000).toFixed(2)} s\n`);

const satir = (ad, r) => console.log(`${ad.padEnd(24)} ${String(r.takip).padStart(7)} ` +
  `${(r.p50 * TUR_MS).toFixed(2).padStart(9)} ${(r.p99 * TUR_MS).toFixed(2).padStart(9)} ` +
  `${(r.enUzun * TUR_MS).toFixed(0).padStart(11)} ${String(r.geciken).padStart(9)} ` +
  `${(r.geciken / r.takip).toFixed(4).padStart(6)} ${`${r.biten}/${r.gelenRapor}`.padStart(9)} ` +
  `${(r.raporOrt * TUR_MS / 1000).toFixed(2).padStart(9)}`);

console.log("tasarim                    takip  p50 (ms)  p99 (ms)  en uzun(ms)  >100 ms     oran  biten/gelen  rapor (s)");
for (const yuva of [2, 4, 8]) satir(`paylasilan y=${yuva}`, kosum({ yuva, ayri: false, isci: 0 }));
for (const yuva of [2, 4]) satir(`paylasilan y=${yuva}, K3=0.25`, kosum({ yuva, ayri: false, isci: 0, oran: 0.25 }));
for (const yuva of [2, 4]) satir(`ayrilmis y=${yuva}, isci=2`, kosum({ yuva, ayri: true, isci: 2 }));

const enAz = (uret) => { for (let y = 1; y <= 12; y += 1) if (uret(y).geciken === 0) return y; return 0; };
const payYuva = enAz((yuva) => kosum({ yuva, ayri: false, isci: 0 }));
const ayriYuva = enAz((yuva) => kosum({ yuva, ayri: true, isci: 2 }));
const raporSaniye = raporSayisi(K3_ORAN) * KOPYA * (RAPOR_KAYIT * TUR_MS / 1000);
const isci = raporSaniye / (K2_PENCERE_DK * 60);
console.log(`\n100 ms ustu takip beklemesini sifirlayan en kucuk yuva: paylasilan ${payYuva}, ayrilmis ${ayriYuva}`);
console.log(`olcekleme birimi -> paylasilan ${payYuva * KOPYA} yuva (hepsi okuma yolunda), ` +
  `ayrilmis ${ayriYuva * KOPYA} yuva + gorev isciligi`);
console.log(`sistem geneli rapor isi = ${raporSaniye.toFixed(0)} isci-saniye / ` +
  `${K2_PENCERE_DK * 60} s = ${isci.toFixed(2)} isci (doluluk 1,00)`);
```

```
tur = 1.2 ms, pencere 30 dk = 1500000 tur, 4 kopya
kopya basina takip 104.17 istek/s, K3 = 0.5 -> kopya basina beklenen rapor 500
rapor isi = 3000 kayit = 3.60 s

tasarim                    takip  p50 (ms)  p99 (ms)  en uzun(ms)  >100 ms     oran  biten/gelen  rapor (s)
paylasilan y=2            187459      0.00   5887.20        9398     54392 0.2902   457/457      4.24
paylasilan y=4            187459      0.00    634.80        2808      3088 0.0165   457/457      3.61
paylasilan y=8            187459      0.00      0.00           0         0 0.0000   457/457      3.60
paylasilan y=2, K3=0.25   187459      0.00   2766.00        4984     15204 0.0811   223/223      3.77
paylasilan y=4, K3=0.25   187459      0.00      0.00        1240       293 0.0016   223/223      3.60
ayrilmis y=2, isci=2      187459      0.00      0.00           0         0 0.0000   457/457      4.14
ayrilmis y=4, isci=2      187459      0.00      0.00           0         0 0.0000   457/457      4.14

100 ms ustu takip beklemesini sifirlayan en kucuk yuva: paylasilan 7, ayrilmis 1
olcekleme birimi -> paylasilan 28 yuva (hepsi okuma yolunda), ayrilmis 4 yuva + gorev isciligi
sistem geneli rapor isi = 7200 isci-saniye / 1800 s = 4.00 isci (doluluk 1,00)
```

Otuz dakikada 187.459 takip isteği ve beklenen 500 rapora karşılık tohumun ürettiği 457 rapor
geldi; sayı Bernoulli varışının bir gerçekleşmesidir ve bütün satırlarda aynıdır.

## Doluluk Düşük, Kuyruk Uzun

Paylaşılan havuzun sayıları ilk bakışta tutarsız görünür. İki yuvalı bir kopyada rapor işi
yuvaların yarısından azını kullanıyor: 457 rapor × 3,60 saniye = 1645 yuva-saniyesi, otuz
dakikalık pencerede iki yuvanın verdiği 3600 yuva-saniyesinin yüzde 46'sı. Takip akışı ise yüzde
12,5 istiyor. Toplam doluluk yüzde 60'ın altında, yani havuz kapasite olarak yeterlidir.

Buna rağmen takip isteklerinin **yüzde 29,02'si** 100 milisaniyeden uzun bekliyor, p99 beklemesi
5887 ms ve en uzun bekleme 9398 ms. Neden yeterli kapasitenin bu tabloyu üretebildiği ortadadır:
kuyruk sırayla boşalır ve önündeki iş 3000 tur sürüyorsa arkasındaki bir turluk iş de 3000 tur
bekler. İki rapor aynı anda çalıştığında iki yuvanın ikisi de kapanır ve o süre boyunca gelen
her takip isteği sıraya girer. **Ortalama doluluk düşükken kuyruğun uzayabilmesi, işlerin
süresinin dağılımından gelir; tek bir doluluk sayısı bu dağılımı saklar.**

Yuva sayısı bunu düzeltir ama pahalıya düzeltir. Dört yuvada oran yüzde 1,65'e, p99 634,80 ms'ye
iner; sekiz yuvada sıfırlanır. Aradaki eşik ölçülmüştür: 100 milisaniye üstü beklemeyi sıfırlayan
en küçük yuva sayısı **yedidir**. Kısa isteğin tek başına ihtiyacı bir yuvadır — ayrılmış
tasarımda ölçülen sayı budur. Yani altı yuva yalnız uzun işin arkasında sıra beklenmesin diye
tutuluyor.

K3'ün duyarlılığı aynı yönü gösteriyor. Rapor isteyen satıcı oranı yarıya indiğinde iki yuvada
etkilenen istek oranı yüzde 29,02'den yüzde 8,11'e, dört yuvada yüzde 1,65'ten yüzde 0,16'ya
düşüyor — ama **sıfırlanmıyor**. Talebin azalması sorunun sıklığını azaltır, yapısını değiştirmez;
tek bir uzun iş bile arkasındaki isteği kendi süresi kadar bekletir.

## Ölçekleme Birimi

Ayrılmış tasarımda rapor işi kuyruğa yazılır ve çağıran bir iş kimliğiyle döner. Takip
isteklerinin ölçüleri her yuva sayısında aynı çıkıyor: p99 sıfır, en uzun bekleme sıfır,
100 milisaniye üstü bekleyen istek yok. Uzun iş yoldan çekildiğinde kısa isteğin kuyruğu da
kayboluyor.

Ödenen bedel rapor tarafındadır ve ölçülmüştür: iki işçiyle ortalama rapor süresi 3,60 saniye
yerine **4,14 saniye**. Rapor artık kendi kuyruğunda sıra bekliyor. Fark yüzde 15'tir ve
istenirse işçi eklenerek kapatılır — çünkü işçi sayısı artık takip akışından bağımsız bir
sayıdır.

Asıl sonuç son üç satırdadır. Paylaşılan tasarımda takip kuyruğunu sıfırlamak için kopya başına
yedi yuva gerekiyor; dört kopyada **28 yuva**. Bu yuvaların hepsi okuma yolundadır: her biri
takip isteği alabilecek biçimde yapılandırılmış, okuma trafiğinin dağıtıldığı kopyalarda durur.
Ayrılmış tasarımda takip için kopya başına bir yuva yetiyor — dört kopyada **4 yuva** — ve rapor
işi ayrı bir işçiliğe geçiyor. O işçiliğin büyüklüğü de aritmetiktir: sistem genelinde 2000 rapor
× 3,60 saniye = 7200 işçi-saniyesi, otuz dakikalık pencerede **4,00 işçi** eder ve bu sayı
doluluk 1,00 demektir, yani gerçek bir tasarım pay bırakır.

**Ayırmanın kazancı bir sayı değil, bir bağımsızlıktır.** Paylaşılan tasarımda rapor talebi
arttığında büyütülecek şey kopyadır; kopya büyütmek okuma yolunu da büyütür, oysa okuma yolunun
kapasiteye ihtiyacı yoktu. Ayrılmış tasarımda rapor talebi işçi sayısını, okuma talebi kopya
sayısını oynatır ve iki sayı birbirine bakmaz. Giriş kursunun tepe okuma hızı 416,67 istek/s
değişmedi; değişen, o hızı karşılayan kopyaların ne kadar büyük olmak zorunda olduğudur — kopya
başına yedi yuvadan bire.

## Özet

- Uzun işin boyu K01'den türetilir: satıcı başına 100 gönderi/gün × 30 gün = 3000 kayıt, tarama
  hızı 833,33 kayıt/s ile 3,60 saniye; takip isteği aynı ölçüde tek kayıttır.
- Paylaşılan havuzda doluluk yüzde 60'ın altındayken bile takip isteklerinin yüzde 29,02'si 100
  ms'den uzun bekliyor, p99 5887 ms: tek bir doluluk sayısı iş sürelerinin dağılımını saklar.
- Kuyruğu sıfırlamanın bedeli yuvadır: 100 ms üstü beklemeyi sıfırlayan en küçük yuva sayısı
  paylaşılan tasarımda yedi, ayrılmış tasarımda birdir.
- K3 varsayımı yarıya indiğinde etkilenen istek oranı yüzde 29,02'den 8,11'e düşüyor ama
  sıfırlanmıyor; talep sorunun sıklığını değiştirir, yapısını değiştirmez.
- Ayrılmış tasarımda takip beklemesi her yuva sayısında sıfır; ödenen bedel iki işçiyle rapor
  süresinin 3,60 saniyeden 4,14 saniyeye çıkmasıdır.
- Ölçekleme birimi ayrışıyor: paylaşılan tasarım dört kopyada 28 yuva ister, ayrılmış tasarım
  4 yuva artı sistem genelinde 4,00 işçilik ister ve iki sayı birbirinden bağımsız oynar.

## Sonraki Adım

Son satırdaki "4,00 işçi" bir kapasite değil bir alt sınırdır; doluluk bire eşit olduğunda kuyruk
boşalmaz. Sayının kendisi de bir soruyu açık bırakıyor: işçi eklemek gerçekten toplama mı
karşılık gelir. Önceki dersin birikme tablosunda tüketici kapasitesi tek bir sayıydı ve o sayının
nereden geldiği sorulmamıştı; oysa kapasite tüketici sayısıyla tüketici başına hızın çarpımıdır
ve çarpanlardan biri sonsuza kadar büyümez. Sonraki ders aynı kuyruktan çeken birden çok
tüketiciyi ele alır: eklenen her tüketicinin boşalma süresine katkısını, katkının nerede
durduğunu ve verimin karşılığında nelerin bozulduğunu ölçer.
