---
title: 'Eşzamansız Tümleştirme'
source: 'https://academia.sh/tr/kurslar/servis-mimarileri/eszamansiz-tumlestirme'
course: 'Servis Mimarileri'
language: tr
updated: '2026-08-17T18:06:53+00:00'
license: 'CC BY-SA 4.0'
---

# Eşzamansız Tümleştirme

Aynı iş akışının eşzamanlı ve olay tabanlı iki gerçekleştirmesinin ölçülmesi: yanıt yolundan düşen iş adımı ve birim sayısı, yayıncının tüketicileri tanımamasıyla doğan sözleşme yükü, olay gövdesindeki her alana bağlı dağıtım birimi sayısı ve yanıtın dönmesiyle etkinin görünmesi arasındaki tutarlılık penceresi.

Önceki dersin bütün sayıları tek bir varsayımdan doğuyordu: çağıran, ardılın işi bitene kadar
bekliyor. Bekleme kaldırıldığında hem tur hem de bağımlılık kapanışı değişir. Bu ders aynı ödünç
verme akışını ikinci kez kurar; bu kez bildirim ve ücretlendirme adımları yanıt yolundan çıkarılıp
bir olayın tüketicisi hâline getirilir ve iki gerçekleştirim aynı ölçülerle karşılaştırılır.

Kuyruk mekaniği, teslim garantisi, geri basınç ve rekabet eden tüketiciler Önbellekleme, Kuyruklar
ve Eşzamansız İşleme kursunda kuruldu ve ölçüldü; burada tekrarlanmaz. Ölçülen şey taşıyıcının
kendisi değil, sınırın iki yanındaki bağın nasıl değiştiğidir.

**SS3 — taşıyıcı, bir ekleme kütüğü ve sabit aralıklı yoklama olarak modellenir.** Gerekçe:
teslim ve sıralama güvenceleri ayrı bir kursta ölçüldüğü için burada taşıyıcının en yalın biçimi
yeterlidir; ölçülen üç nicelik (yanıt yolundaki birim, alan başına bağlı birim, tutarlılık
penceresi) taşıyıcının türünden bağımsızdır. Kütük gerçek bir dosyadır, yoklama gerçek bir süreçte
koşar; model olan yalnız taşıyıcının yalınlığıdır.

## İki Gerçekleştirim, Tek Kaynak

Ödünç servisi iki kipte koşar. Eşzamanlı kipte iki ardılını çağırır ve ikisinin de yanıtını
bekler. Olay kipinde aynı gövdeyi kütüğe yazar ve döner. Fark tek satırdadır, ama o satır servisin
yapılandırmasını da değiştirir: olay kipinde ardıl adresi listesi boştur.

```js
// odunc.mjs — <kip: eszamanli|olay> <port> <bildirim-port> <ucret-port>; uzun omurlu surec
import { createServer } from "node:http";
import { appendFileSync } from "node:fs";
const [kip, port, pb, pu] = process.argv.slice(2);
if (!port) { console.log("kullanim: node odunc.mjs <kip> <port> <bildirim-port> <ucret-port>"); process.exit(1); }
const IS = 25;                                   // odunc kaydinin yazilmasi (ms)
const ARDIL = kip === "eszamanli" ? [pb, pu] : [];   // olay kipinde yayinci ardil adresi tasimaz
let sira = 0;

createServer(async (istek, yanit) => {
  if (istek.url === "/ardil") { yanit.end(JSON.stringify({ ardil: ARDIL.length })); return; }
  await new Promise((c) => setTimeout(c, IS));
  sira += 1;
  const olay = { tur: "odunc-verildi", sira: sira, uyeId: 7, nushaId: 400 + sira,
    gecikmeGunu: 0, baslik: "Kitap odunc verildi" };
  const govde = JSON.stringify(olay);
  if (kip === "olay") appendFileSync("olaylar.log", `${govde}\n`);
  else await Promise.all(ARDIL.map((p) =>
    fetch(`http://127.0.0.1:${p}/is`, { method: "POST", body: govde })));
  yanit.end(govde);
}).listen(Number(port));
```

Bildirim ve ücretlendirme birimleri de tek kaynaktan koşar ve iki rolü birden üstlenir: uç olarak
çağrıldıklarında gövdeyi istekten alırlar, tüketici olarak koştuklarında aynı gövdeyi kütükten
okurlar. İşin kendisi iki durumda da aynı işlevdir; değişen yalnız gövdenin nereden geldiğidir.

```js
// birim.mjs — <ad: bildirim|ucret> <port> <yokla: 0|1>; hem uc olarak hem tuketici olarak kosar
import { createServer } from "node:http";
import { appendFileSync, existsSync, readFileSync } from "node:fs";
const [ad, port, yokla] = process.argv.slice(2);
if (!port) { console.log("kullanim: node birim.mjs <ad> <port> <yokla>"); process.exit(1); }
const IS = 25, ARALIK = 200;                     // birimin isi ve yoklama araligi (ms)
const SOZLESME = {                               // her birimin olay govdesinden okudugu alanlar
  bildirim: (o) => `${o.uyeId} nolu uyeye ${o.baslik} bildirimi gitti`,
  ucret: (o) => `${o.uyeId} nolu uye, nusha ${o.nushaId}, ${o.gecikmeGunu} gun gecikme`,
};
const isle = async (o) => {
  await new Promise((c) => setTimeout(c, IS));
  appendFileSync(`etki-${ad}.log`, `${o.sira} ${SOZLESME[ad](o)}\n`);
};

createServer(async (istek, yanit) => {
  let s = "";
  for await (const p of istek) s += p;
  await isle(JSON.parse(s));
  yanit.end("tamam");
}).listen(Number(port));

let okunan = 0, mesgul = false;
if (yokla === "1") setInterval(async () => {
  if (mesgul || !existsSync("olaylar.log")) return;
  mesgul = true;
  const satir = readFileSync("olaylar.log", "utf8").split("\n").filter(Boolean);
  while (okunan < satir.length) { await isle(JSON.parse(satir[okunan])); okunan += 1; }
  mesgul = false;
}, ARALIK);
```

## Ölçüm Aracı

Araç iki iş yapar. Koşum kipinde üç istek gönderip turu bulur, sonra etkilerin oturmasını bekler
ve bir istek daha göndererek yanıtın döndüğü anda yeni etkinin görünüp görünmediğine bakar. Aynı
gözlemi 600 milisaniye sonra yineler. Sözleşme kipinde hiçbir süreç ayakta değildir; yalnız iki
kaynak dosya okunur ve olay gövdesindeki her alanın kaç dağıtım birimini bağladığı sayılır.

```js
// olc.mjs — <kip: eszamanli|olay|sozlesme>; ilk iki kip surecler ayaktayken kosar
import { existsSync, readFileSync } from "node:fs";
const IS = 25, UC = { odunc: 8951 }, BIRIM = ["bildirim", "ucret"];
const bekle = (ms) => new Promise((c) => setTimeout(c, ms));
const etki = () => BIRIM.reduce((s, a) => s + (existsSync(`etki-${a}.log`)
  ? readFileSync(`etki-${a}.log`, "utf8").split("\n").filter(Boolean).length : 0), 0);
const iste = () => fetch(`http://127.0.0.1:${UC.odunc}/is`).then((y) => y.text());
const [kip] = process.argv.slice(2);

if (kip === "eszamanli" || kip === "olay") {
  const { ardil } = await (await fetch(`http://127.0.0.1:${UC.odunc}/ardil`)).json();
  const sure = [];
  for (let i = 0; i < 3; i += 1) {
    const t = performance.now();
    await iste();
    sure.push(performance.now() - t);
  }
  const tur = Math.floor(sure.sort((a, b) => a - b)[1] / IS);
  await bekle(600);
  const once = etki();
  await iste();
  const hemen = etki() > once;                   // yanit dondugu anda yeni etki gorunur mu
  await bekle(600);
  const sonra = etki() > once;
  console.log(`${kip.padEnd(12)}${String(tur).padStart(11)}${String(1 + ardil).padStart(23)}` +
    `${String(ardil).padStart(27)}${(hemen ? "evet" : "hayir").padStart(19)}` +
    `${(sonra ? "evet" : "hayir").padStart(19)}${`${etki()}/8`.padStart(13)}`);
} else if (kip === "sozlesme") {
  const olayBlok = readFileSync("odunc.mjs", "utf8").match(/const olay = \{([\s\S]*?)\};/)[1];
  const alan = [...olayBlok.matchAll(/(\w+):/g)].map((m) => m[1]);
  const kaynak = readFileSync("birim.mjs", "utf8");
  const tuketici = {};
  for (const m of kaynak.matchAll(/^ {2}(\w+): \(o\) => (.*)$/gm)) {
    tuketici[m[1]] = [...m[2].matchAll(/o\.(\w+)/g)].map((x) => x[1]);
  }
  const ortak = [...kaynak.replace(/^ {2}\w+: \(o\) => .*$/gm, "").matchAll(/o\.(\w+)/g)]
    .map((x) => x[1]);
  const tk = Object.keys(tuketici);
  console.log(`${"olay alani".padEnd(14)}${"yayinci".padStart(9)}${"okuyan tuketici".padStart(17)}` +
    `${"ortak kod".padStart(11)}${"bagli dagitim birimi".padStart(22)}`);
  let toplam = 0;
  for (const a of alan) {
    const okuyan = tk.filter((t) => tuketici[t].includes(a));
    const o = ortak.includes(a) ? 1 : 0;
    const bagli = 1 + (o ? tk.length : okuyan.length);
    toplam += bagli;
    console.log(`${a.padEnd(14)}${"1".padStart(9)}${String(okuyan.length).padStart(17)}` +
      `${String(o).padStart(11)}${String(bagli).padStart(22)}`);
  }
  console.log(`${alan.length} alanli olay govdesi, ${tk.length} tuketici birimi; ` +
    `alan basina ortalama bagli birim ${(toplam / alan.length).toFixed(2)}`);
  console.log(`hicbir tuketicinin okumadigi alan: ` +
    `${alan.filter((a) => tk.every((t) => !tuketici[t].includes(a)) && !ortak.includes(a)).join(", ")}`);
}
```

```bash
rm -f olaylar.log etki-bildirim.log etki-ucret.log
printf '%-12s%11s%23s%27s%19s%19s%13s\n' kip "yanit turu" \
  "yanit yolundaki birim" "yayincinin tanidigi ardil" "yanit aninda etki" "600 ms sonra" "etki satiri"
node birim.mjs bildirim 8952 0 &
node birim.mjs ucret 8953 0 &
node odunc.mjs eszamanli 8951 8952 8953 &
sleep 1
node olc.mjs eszamanli
pkill -f "node birim.mjs" ; pkill -f "node odunc.mjs" ; sleep 0.3
rm -f etki-bildirim.log etki-ucret.log

node birim.mjs bildirim 8952 1 &
node birim.mjs ucret 8953 1 &
node odunc.mjs olay 8951 8952 8953 &
sleep 1
node olc.mjs olay
pkill -f "node birim.mjs" ; pkill -f "node odunc.mjs" ; sleep 0.3
echo
node olc.mjs sozlesme
```

```
kip          yanit turu  yanit yolundaki birim  yayincinin tanidigi ardil  yanit aninda etki       600 ms sonra  etki satiri
eszamanli             2                      3                          2               evet               evet          8/8
olay                  1                      1                          0              hayir               evet          8/8

olay alani      yayinci  okuyan tuketici  ortak kod  bagli dagitim birimi
tur                   1                0          0                     1
sira                  1                0          1                     3
uyeId                 1                2          0                     3
nushaId               1                1          0                     2
gecikmeGunu           1                1          0                     2
baslik                1                1          0                     2
6 alanli olay govdesi, 2 tuketici birimi; alan basina ortalama bagli birim 2.17
hicbir tuketicinin okumadigi alan: tur
```

## Yanıt Yolundan Düşen İş

İlk iki kolon kazancı veriyor. Eşzamanlı gerçekleştirmede yanıt iki tur sürüyor: ödünç kaydının
yazılması ve ardılların işi. Olay tabanlı gerçekleştirmede aynı istek bir turda dönüyor, çünkü
yanıt yolunda yalnız kütüğe bir satır ekleme kalıyor. Son kolon işin kaybolmadığını gösteriyor:
her iki gerçekleştirmede de dört istek sekiz etki satırı üretiyor.

Üçüncü kolon kazancın asıl büyüklüğünü veriyor. Yanıt yolundaki dağıtım birimi sayısı üçten bire
iniyor. Önceki dersin ölçüsüyle okunduğunda bunun anlamı açıktır: bildirim ve ücretlendirme
birimleri ödünç ucunun bağımlılık kapanışından çıkmıştır. Eşzamanlı gerçekleştirmede bu iki
birimden birinin kapanması ödünç isteğini düşürürken, olay tabanlı gerçekleştirmede kapanma yanıt
yolunda hiç görünmez.

## Sözleşmenin Yayılması

Dördüncü kolon bedelin ilk yarısını veriyor. Eşzamanlı gerçekleştirmede yayıncı iki ardıl adresi
taşır: kimi çağırdığını bilir, çağrı yerinden okunabilir. Olay kipinde bu sayı sıfırdır. Yayıncı
artık tüketicilerini tanımaz; bu tam olarak istenen gevşek bağlanmadır ve tam olarak sözleşme
yükünün kaynağıdır.

İkinci tablo bu yükü sayıya çeviriyor. Olay gövdesinde altı alan var ve her alan ortalama 2,17
dağıtım birimini bağlıyor. Üyelik kimliğini iki tüketici birden okuyor: alanın adı ya da anlamı
değiştiğinde üç birim birden dokunulmak zorundadır. Sıra numarası hiçbir tüketicinin sözleşme
satırında görünmüyor ama ortak işleme kodunda okunuyor, dolayısıyla o da üç birimi bağlıyor.

Son satır eşzamansız tümleştirmenin karakteristik sorunudur: `tur` alanını hiçbir tüketici
okumuyor. Yayıncı gövdeye koyduğu her alanı sonsuza kadar savunmak zorundadır, çünkü hangi alanın
okunduğunu göremez. Eşzamanlı çağrıda bu bilgi çağrı yerinden okunabilirdi; kütüğün karşı tarafında
okunamaz. Sözleşme evrimi ve tüketici koruması bu kursun son konusunda ele alınacaktır.

## Tutarlılık Penceresi

Beşinci ve altıncı kolon yeni arıza kipini gösteriyor. Eşzamanlı gerçekleştirmede yanıt döndüğü an
etki hazırdır: çağıran, ücret satırının yazıldığını bilerek döner. Olay tabanlı gerçekleştirmede
yanıt döndüğü anda etki yoktur ve 600 milisaniye sonra vardır. Aradaki aralık **tutarlılık
penceresi**dir ve bu düzenekte üst sınırı bellidir: yoklama aralığı artı tüketicinin iş süresi,
yani 225 milisaniye. Ölçüm bu sınırı iki uçtan doğruluyor — pencerenin başında etki yok, sonunda
var.

Pencerenin içinde sistem tutarsızdır ve tutarsızlık gözlenebilir: o aralıkta üyenin hesabını
okuyan bir istek ödünç kaydını görür, ücret satırını görmez. Bu, eşzamanlı gerçekleştirmede
bulunmayan bir durumdur ve kaldırılamaz; yalnızca daraltılabilir ve arayüzde karşılanabilir.
İkinci yeni arıza kipi de aynı yerden çıkar: tüketici kapalıyken olaylar kütükte birikir, yanıt
süresi hiç bozulmaz ve arıza yanıt yolunda görünmez. Sorun ancak biriken olaylara bakan biri
varsa fark edilir.

Üçlü şöyle toparlanır. **Ucuzlayan:** yanıt turu 2'den 1'e, yanıt yolundaki birim 3'ten 1'e indi;
iki tüketici birimi bağımlılık kapanışından çıktı. **Pahalılaşan:** sözleşme üç dağıtım birimine
yayıldı, alan başına ortalama 2,17 birim bağlandı ve yayıncının tanıdığı ardıl sayısı sıfıra
düştüğü için hangi alanın okunduğu koddan görünmez oldu. **Doğan arıza kipi:** tutarlılık
penceresi ve yanıt yolunda görünmeyen tüketici arızası.

## Özet

- Aynı iş akışı olay tabanlı kurulduğunda yanıt turu 2'den 1'e, yanıt yolundaki dağıtım birimi
  3'ten 1'e iniyor; dört istek her iki gerçekleştirmede de 8 etki satırı üretiyor.
- Yayıncının tanıdığı ardıl sayısı 2'den 0'a düşüyor; gevşek bağlanmanın kaynağı da sözleşme
  yükünün kaynağı da bu sayıdır.
- Altı alanlı olay gövdesinde alan başına ortalama 2,17 dağıtım birimi bağlı; üyelik kimliği üç
  birimi birden bağlıyor ve `tur` alanını hiçbir tüketici okumuyor.
- Tutarlılık penceresi ölçümle iki uçtan doğrulandı: yanıt anında etki yok, 600 ms sonra var; üst
  sınır yoklama aralığı artı tüketici işidir.
- Eşzamansız tümleştirme tüketici arızasını yanıt yolundan çıkarır; arıza artık yanıt süresinde
  değil, biriken olaylarda görünür.

## Sonraki Adım

İki konu boyunca sınırın iki yanı çalışıldı: sınırın nereden geçeceği, karşıya nasıl çağrı
yapılacağı ve bazı çağrıların hiç yapılmayıp olaya dönüştürülmesi. Bütün bu düzenlemelerde bir
taraf hiç ele alınmadı — dışarısı. İstemci hâlâ servislerin adreslerini tek tek biliyor, her
servis kendi kimlik denetimini kendi kodunda taşıyor ve aynı hız sınırı kuralı birden çok yerde
yazılı duruyor. Sonraki ders bu yinelenmeyi sayar: hangi kenar sorumluluğu kaç serviste kaç satır
olarak tekrarlanmış, bu sorumluluklar tek bir yere taşındığında kaç dosya ve kaç uç değişiyor ve
istek başına kaç atlama ekleniyor.
