---
title: 'Elçi ve Yan Araba Kalıpları'
source: 'https://academia.sh/tr/kurslar/trafik-katmani/elci-ve-yan-araba-kaliplari'
course: 'Trafik Katmanı'
language: tr
updated: '2026-08-17T18:11:02+00:00'
license: 'CC BY-SA 4.0'
---

# Elçi ve Yan Araba Kalıpları

Ortak işin ayrı bir yardımcı sürece verilmesi: elçinin dış sözleşmeyi servis kodundan ayırdığının iki taşıyıcı sürümüyle ölçülmesi, yan arabanın çalışma zamanı bağımsızlığı ile yeniden yayınlanan birim sayısına etkisi ve süreç sayısının ödettiği yerel durak.

Önceki ders kenar birimi sayısını 1'den 3'e çıkardı ve bir sorun bıraktı: aynı ortak kod her
birimde tekrarlanıyor. Ortak kodu paylaşmanın bilinen yolu onu bir kitaplığa almaktır, ama
kitaplık iki şey dayatır — her birim aynı çalışma zamanında olmalı ve kitaplığın sürümü
değiştiğinde her birim yeniden yapılıp yayınlanmalıdır.

Başka bir yol, ortak işi **ayrı bir sürece** vermektir. **Yan araba** (sidecar), ana süreçle
aynı dağıtım biriminde koşan ve onun ortak işlerini üstlenen yardımcı süreçtir. **Elçi**
(ambassador), aynı yerleşimin giden çağrılara uygulanmış hâlidir: servis yerel bir adrese
çağrı yapar, elçi dış hedefi bulur ve dış sözleşmeye çevirir. İkisi de kalıp olarak yeni
değildir — Alan Odaklı Tasarım kursundaki bağlantı noktaları ve bağdaştırıcılar dersi aynı
ayrımı kod düzeyinde kurmuştu. Burada ele alınan şey kalıbın kendisi değil, **dağıtım birimi
düzeyindeki** karşılığı ve o karşılığın ödettiği sayılar.

## Elçi: Dış Sözleşmenin Servis Kodundan Ayrılması

Teslimat operasyonu bağlamı gönderi durumunu dış bir taşıyıcıdan alır. Taşıyıcı aynı bilgiyi
iki ayrı sözleşmeyle sunuyor; düzenek ikisini de gerçek bir süreç olarak koşturur.

```js
// elci/tasiyici.mjs — dis tasiyici servisi 8481: ayni bilgiyi iki ayri sozlesmeyle sunar
import { createServer } from "node:http";

const KAYIT = { "TR-4821": { kod: "OFD", bolge: "35", zaman: "2026-03-11T08:24:00Z" } };

createServer((istek, yanit) => {
  const [surum, , kuyruk] = istek.url.split("/").filter(Boolean);
  const no = surum === "v1" ? new URL(istek.url, "http://y").searchParams.get("no") : kuyruk;
  const k = KAYIT[no];
  const govde = !k ? { error: "not_found" }
    : surum === "v1" ? { code: k.kod, zone: k.bolge, ts: Date.parse(k.zaman) / 1000 }
      : { state: "out_for_delivery", region: { code: k.bolge }, updatedAt: k.zaman };
  yanit.writeHead(k ? 200 : 404, { "Content-Type": "application/json" });
  yanit.end(JSON.stringify(govde));
}).listen(8481, "127.0.0.1", () => console.log("tasiyici 127.0.0.1:8481"));
```

Elçi ayrı bir süreçtir ve hangi sözleşmeye konuşacağını başlatma argümanından alır. Yaptığı
iş üç parçadır: dış yolu kurmak, dış gövdeyi iç biçime çevirmek ve dış çağrıyı ölçmek.

```js
// elci/elci.mjs — elci sureci: yerel adresi dis sozlesmeye cevirir. Kullanim: node elci/elci.mjs v1 8480
import { createServer } from "node:http";

const [surum, port] = [process.argv[2], Number(process.argv[3])];
const DURUM_ADI = { OFD: "dagitimda", out_for_delivery: "dagitimda" };
let son = { yol: "-", bayt: 0 };                   // en son dis cagrinin yolu ve govde bayti

const disYol = (no) => (surum === "v1" ? `/v1/durum?no=${no}` : `/v2/status/${no}`);
const cevir = (d) => (surum === "v1"
  ? { durum: DURUM_ADI[d.code], bolge: d.zone, guncellenme: new Date(d.ts * 1000).toISOString() }
  : { durum: DURUM_ADI[d.state], bolge: d.region.code,
    guncellenme: new Date(d.updatedAt).toISOString() });

createServer(async (istek, yanit) => {
  const [kok, no] = istek.url.split("/").filter(Boolean);
  if (kok === "sayac") {
    yanit.writeHead(200, { "Content-Type": "application/json" });
    return yanit.end(JSON.stringify({ surum, ...son }));
  }
  const yol = disYol(no);
  const y = await fetch(`http://127.0.0.1:8481${yol}`);
  const metin = await y.text();
  son = { yol, bayt: Buffer.byteLength(metin) };
  const govde = y.ok ? cevir(JSON.parse(metin)) : { hata: "bulunamadi" };
  yanit.writeHead(y.ok ? 200 : 404, { "Content-Type": "application/json" });
  yanit.end(JSON.stringify({ takipNo: no, ...govde }));
}).listen(port, "127.0.0.1", () => console.log(`elci-${surum} 127.0.0.1:${port}`));
```

Ölçüm betiği servis kodunun yerine geçer: iki elçiye de aynı yerel adresi, aynı yolu ve aynı
isteği verir. Servis kodunun tamamı tek satırdır ve içinde dış adres, dış yol ya da dış alan
adı geçmez.

```js
// elci/olc.mjs — servis kodu iki elciye ayni istegi yapar; disa cikan sozlesme farkli
const al = async (url) => {
  const y = await fetch(url);
  const metin = await y.text();
  return { bayt: Buffer.byteLength(metin), metin };
};

// Servis kodunun tamami: yerel bir adrese sabit bir yol ile istek yapar.
const servisIstegi = (elciPort) => `http://127.0.0.1:${elciPort}/durum/TR-4821`;

const YERLESIM = [["v1", 8480], ["v2", 8489]];
const sonuc = [];
for (const [surum, port] of YERLESIM) {
  const yanit = await al(servisIstegi(port));
  const sayac = JSON.parse((await al(`http://127.0.0.1:${port}/sayac`)).metin);
  sonuc.push({ surum, istek: "/durum/TR-4821", yanitBayt: yanit.bayt, yanit: yanit.metin,
    disYol: sayac.yol, disBayt: sayac.bayt });
}

console.log(`${"elci".padEnd(6)}${"servis istegi".padEnd(17)}${"yanit B".padStart(8)}` +
  `${"dis bayt".padStart(10)}  dis yol`);
for (const s of sonuc) {
  console.log(`${s.surum.padEnd(6)}${s.istek.padEnd(17)}${String(s.yanitBayt).padStart(8)}` +
    `${String(s.disBayt).padStart(10)}  ${s.disYol}`);
}
const ayni = new Set(sonuc.map((s) => s.yanit));
console.log(`\nservise donen govde (v1): ${sonuc[0].yanit}`);
console.log(`servise donen govde (v2): ${sonuc[1].yanit}`);
console.log(`servisin gordugu sozlesme = ${ayni.size}, dis sozlesme = ${sonuc.length}`);
console.log(`servis kodunda dis adres = 0, dis sozlesme degisince duzenlenen servis dosyasi = 0`);
```

```bash
node elci/tasiyici.mjs & t=$!
curl -s --retry 20 --retry-connrefused --retry-delay 0 -o /dev/null http://127.0.0.1:8481/v1/durum?no=TR-4821
node elci/elci.mjs v1 8480 & a=$!
curl -s --retry 20 --retry-connrefused --retry-delay 0 -o /dev/null http://127.0.0.1:8480/sayac
node elci/elci.mjs v2 8489 & b=$!
curl -s --retry 20 --retry-connrefused --retry-delay 0 -o /dev/null http://127.0.0.1:8489/sayac
node elci/olc.mjs
kill $t $a $b
```

```
tasiyici 127.0.0.1:8481
elci-v1 127.0.0.1:8480
elci-v2 127.0.0.1:8489
elci  servis istegi     yanit B  dis bayt  dis yol
v1    /durum/TR-4821         95        42  /v1/durum?no=TR-4821
v2    /durum/TR-4821         95        86  /v2/status/TR-4821

servise donen govde (v1): {"takipNo":"TR-4821","durum":"dagitimda","bolge":"35","guncellenme":"2026-03-11T08:24:00.000Z"}
servise donen govde (v2): {"takipNo":"TR-4821","durum":"dagitimda","bolge":"35","guncellenme":"2026-03-11T08:24:00.000Z"}
servisin gordugu sozlesme = 1, dis sozlesme = 2
servis kodunda dis adres = 0, dis sozlesme degisince duzenlenen servis dosyasi = 0
```

Ölçümün taşıdığı sayı son satırlardadır: dış sözleşme 2, servisin gördüğü sözleşme 1. İki
elçiye giden istek de aynı yola gitti ve iki elçiden dönen gövde birebir aynı 95 bayt. Dış
tarafta ise yollar da baytlar da farklı: `v1` çağrısı 42 bayt, `v2` çağrısı 86 bayt taşıyor,
yani aynı üç bilgi için ikinci sözleşme 2,05 kat gövde kullanıyor.

Sayaç bir denetim aracı olarak da işe yarıyor. Çevirinin eksik kalması, örneğin zaman
damgasının bir sözleşmede olduğu gibi bırakılması, `servisin gordugu sozlesme` sayısını 1
yerine 2 yapardı. Elçinin işi "isteği iletmek" değil, iç sözleşmeyi **tek** tutmaktır ve bu
sayı onun ölçüsüdür.

## Yan Araba: Ortak Yeteneğin Dağıtım Birimine Bağlanması

İkinci ölçüm süreç içi bir modeldir: gerçek dağıtım aracı, kapsayıcı ya da yayınlama yoktur.
Model bu kursta oluşan altı dağıtım birimini sayar — üç servis (takip, olay, ücret) ve önceki
dersin eklediği üç kenar birimi — ve ikisinin iki ayrı çalışma zamanında olduğunu varsayar.

```js
// elci/birim.mjs — ortak yetenegin iki yerlesimi; dagitim birimi duzeyinde surec ici model
const BIRIM = {                                  // bu kursta olusan alti dagitim birimi
  takip: "A", olay: "A", ucret: "B",             // A ve B: iki ayri calisma zamani
  "kenar-mobil": "A", "kenar-web": "A", "kenar-panel": "B",
};
const YERLESIM = {
  "kitaplik": { ayriSurec: false, calismaZamani: ["A"] },
  "yan araba": { ayriSurec: true, calismaZamani: ["A", "B"] },
};

const olc = (y) => {
  const birim = Object.entries(BIRIM);
  const kullanabilen = birim.filter(([, z]) => y.calismaZamani.includes(z)).length;
  return {
    "ortak yetenegi kullanabilen birim": `${kullanabilen}/${birim.length}`,
    "surum degisince yeniden yapilan birim": y.ayriSurec ? 1 : kullanabilen,
    "yeniden yayinlanan servis kodu": y.ayriSurec ? 0 : kullanabilen,
    "dagitim birimi basina surec": y.ayriSurec ? 2 : 1,
    "toplam surec": birim.length * (y.ayriSurec ? 2 : 1),
    "kenar birimindeki yerel durak": y.ayriSurec ? 2 : 1,
  };
};

const ALAN = Object.keys(olc(YERLESIM["yan araba"]));
const olcum = Object.entries(YERLESIM).map(([ad, y]) => ({ ad, ...olc(y) }));
console.log(`dagitim birimi = ${Object.keys(BIRIM).length} ` +
  `(calisma zamani A: ${Object.values(BIRIM).filter((z) => z === "A").length}, ` +
  `B: ${Object.values(BIRIM).filter((z) => z === "B").length})`);
console.log(`${"olcu".padEnd(38)}${olcum.map((o) => o.ad.padStart(12)).join("")}`);
for (const a of ALAN) console.log(`${a.padEnd(38)}${olcum.map((o) => String(o[a]).padStart(12)).join("")}`);

// K01 Kabaca Buyukluk Hesabi: uctaki tepe 513.89 istek/s (hesap sinifi)
const UC_TEPE = 513.89;
console.log("");
for (const o of olcum) {
  const durak = 1 + o["kenar birimindeki yerel durak"];      // ag gecidi duragi + kenar duraklari
  console.log(`${o.ad.padEnd(10)} durak ${durak} -> durak-istek/s = ${(UC_TEPE * durak).toFixed(2)}`);
}
```

```
dagitim birimi = 6 (calisma zamani A: 4, B: 2)
olcu                                      kitaplik   yan araba
ortak yetenegi kullanabilen birim              4/6         6/6
surum degisince yeniden yapilan birim            4           1
yeniden yayinlanan servis kodu                   4           0
dagitim birimi basina surec                      1           2
toplam surec                                     6          12
kenar birimindeki yerel durak                    1           2

kitaplik   durak 2 -> durak-istek/s = 1027.78
yan araba  durak 3 -> durak-istek/s = 1541.67
```

## Sayıların Okunması

İlk satır kitaplık yerleşiminin sessiz kısıtını gösteriyor: ortak yeteneği altı birimin
yalnız dördü kullanabiliyor, çünkü ikisi başka bir çalışma zamanında. Bu birimler ya yeteneği
kendileri yeniden yazar ya da onsuz kalır; iki durumda da "ortak yetenek" sıfatı yanlıştır.
Yan araba yerleşiminde sayı 6/6 olur, çünkü iki süreç arasındaki bağ bir işlev çağrısı değil
bir yerel çağrıdır.

İkinci ve üçüncü satırlar yayınlama maliyetini ayırıyor. Ortak yeteneğin sürümü
değiştiğinde kitaplık yerleşiminde dört birim yeniden yapılıp yayınlanır ve dört servis kodu
yeniden yayınlanmış olur. Yan araba yerleşiminde yeniden yapılan birim 1, yeniden yayınlanan
servis kodu 0'dır: servislerin yapıtı değişmez. Bu, önceki derslerin "tekrarlanan satır"
ölçüsünün dağıtım düzeyindeki karşılığıdır — orada aynı kodun kaç dosyada durduğu, burada aynı
değişikliğin kaç yapıtı yenilettiği sayılıyor.

Son üç satır bedeli veriyor ve bedel ucuz değil. Dağıtım birimi başına süreç 1'den 2'ye,
toplam süreç 6'dan 12'ye çıkıyor. Her kenar birimi içinde bir yerel durak daha oluşuyor ve
bu, ilk dersin `durak-istek/s` ölçüsünü büyütüyor.

## Hesaba Dönüş

İlk ders K01'in uçtaki tepe hızını (513,89 istek/s) alıp ağ geçidiyle birlikte her isteğin iki
durağa dokunduğunu ve durak-istek hızının 1027,78'e çıktığını hesaplamıştı. Yan araba üçüncü
durağı ekliyor: 513,89 × 3 = 1541,67 durak-istek/s. Sayı K01'in hiçbir varsayımını değiştirmiyor
— günlük sorgu, gövde boyutu ve tepe çarpanı aynı kalıyor — ama aynı istek hızının sistemde kaç
yerde işlendiğini üç katına çıkarıyor.

Bu, süre ölçüsü değildir; bu makinede ölçülmüş bir gecikme yoktur ve yazılmaz. Söylediği şey
şudur: bir yardımcı süreç kararı, hiçbir varsayımı değiştirmeden K01'in tepe hızını sistemin
üç ayrı yerinde birden görünür kılar. Kararın savunması bu yüzden "ilgileri ayırıyor"
cümlesiyle yazılamaz; yanına 6/6, 1, 0, 12 ve 1541,67 sayıları yazılır.

## Özet

- Yan araba ana süreçle aynı dağıtım biriminde koşan yardımcı süreçtir; elçi aynı yerleşimin
  giden çağrılara uygulanmış hâlidir ve dış hedefi ile dış sözleşmeyi üstlenir.
- Elçi ölçümünde dış sözleşme 2, servisin gördüğü sözleşme 1 çıktı: iki elçi de aynı 95 baytlık
  gövdeyi döndürdü, dışarıda 42 ve 86 bayt taşındı.
- Servis kodunda dış adres 0 ve dış sözleşme değiştiğinde düzenlenen servis dosyası 0; eksik
  bir çeviri `servisin gordugu sozlesme` sayısını 1'den 2'ye çıkararak kendini belli eder.
- Kitaplık yerleşiminde ortak yeteneği altı birimin dördü kullanabiliyor ve sürüm değiştiğinde
  dört servis kodu yeniden yayınlanıyor; yan arabada 6/6 kullanabiliyor, yeniden yapılan birim 1,
  yeniden yayınlanan servis kodu 0.
- Ödenen sayılar: dağıtım birimi başına süreç 1'den 2'ye, toplam süreç 6'dan 12'ye çıkıyor.
- K01'e dönüş: uçtaki 513,89 istek/s üçüncü durakla birlikte 1541,67 durak-istek/s'ye çıkıyor;
  hiçbir varsayım değişmiyor, aynı hız üç yerde işleniyor.

## Sonraki Adım

Beş ders boyunca kenara yerleştirilen her iş bir kazanç ve bir bedelle yazıldı, ama hepsinin
ortak bir kabulü vardı: kenara ulaşan istek işlenmeye değer bir istektir. Oysa uçtaki tepe
hızın bir bölümü hiçbir zaman yanıtlanmayacak isteklerden oluşur — eksik alanlı gövdeler,
tanınmayan yollar, sınırı aşan boyutlar, biçimsiz belirteçler. Bu istekler uygulamaya
ulaştığında uygulamanın kaynaklarını, ulaşmadan önce durdurulduğunda kenarın kaynaklarını
harcar. Son ders doğrulamayı ayrı bir katmana yalıtan kapı bekçisi kalıbını ele alır ve
geçersiz isteğin uygulamaya ulaşma oranını ölçüp K01'in uçtaki tepe hızına uygular.
