Ders 03 / 15
İletişim Biçimleri
Aynı iç çağrının uzak yordam, kaynak temelli ve sorgu temelli biçimlerde yazılıp servis sınırına özgü üç ölçüyle karşılaştırılması: bir dış istek için yapılan iç çağrı sayısı, iç sınırdan geçen bayt ve çağıranın bilmek zorunda olduğu ad sayısı; iç bayt hacminin giriş kursunun tepe okuma hızıyla çarpılıp iç sınır bant genişliğine çevrilmesi.
İçindekiler
Adres artık çalışma zamanında bulunuyor ve liste kendini güncelliyor. İki servisin birbirine ulaşabilmesi için gereken parçalar tamam; ama ulaştıktan sonra ne konuşacakları seçilmedi. Trafik Katmanı kursunun ağ geçidi teslimat operasyonu ile ücretlendirme servisini paralel çağırıp yanıtlarını tek gövdede birleştiriyordu ve o iki çağrının biçimi hiçbir yerde tartışılmadı.
Üç biçim Web API Tasarımı kursunda kurulmuştu: uzak yordam çağrısı, kaynak temelli ve sorgu temelli. O kurs üçünü istemci sınırında karşılaştırdı ve ölçüleri oraya aitti — istek sayısı, aşırı veri çekme oranı, gereksinim değiştiğinde hangi tarafın değişmek zorunda kaldığı. Servis sınırı farklı bir yerdir: iki uç da bizimdir, aşırı veri çekme elle düzeltilebilen bir kusurdur ve istemci sürümünü bekleme sorunu yoktur. Protokol ve şema dili bu derste yeniden anlatılmaz; ölçülen şey seçimin sistem üzerindeki üç sonucudur — bir dış istek için yapılan iç çağrı sayısı, iç sınırdan geçen bayt ve çağıranın bilmek zorunda olduğu ad sayısı.
Düzenek
İki alan servisi ayrı süreçlerdir ve aynı veriyi üç biçimde sunar. Alan kümeleri M18’de kurulan iki bağlamı sürdürür: teslimat operasyonu rota ve taşıyıcı bilgisini, ücretlendirme tarife ve sözleşme bilgisini taşır. Ağ geçidinin yanıttan okuduğu alanlar K01’in V5 varsayımından gelir — durum, bölge, güncellenme zamanı, son rota adımları — ve buna ücretin net tutarı eklenir.
// iletisim/servis.mjs — iki alan servisi (teslimat operasyonu 8471, ucretlendirme 8472), // her biri ayni veriyi uc bicimde sunuyor: kaynak temelli, uzak yordam ve sorgu temelli. import { createServer } from "node:http"; const GONDERI = { "TR-4821": { takipNo: "TR-4821", durum: "dagitimda", bolge: "35", guncellenme: "2026-03-11T08:24:00Z", rota: ["34", "41", "35"], tasiyici: "T3", agirlikGram: 2400, hacimDm3: 12, sozlesmeNo: "S7", cikisSubesi: "34-021", varisSubesi: "35-114" } }; const UCRET = { "TR-4821": { takipNo: "TR-4821", tarife: 9600, indirim: 1440, net: 8160, sozlesmeNo: "S7", donem: "2026-03", kalem: 3, vergiOrani: 0.2 } }; const YORDAM = { // amaca ozel, sunucunun sabitledigi yanitlar takipOzeti: (k) => ({ durum: k.durum, bolge: k.bolge, guncellenme: k.guncellenme, rota: k.rota }), netUcret: (k) => ({ net: k.net }), }; const govdeOku = (istek) => new Promise((coz) => { let m = ""; istek.on("data", (p) => (m += p)); istek.on("end", () => coz(m)); }); const sun = (port, ad, tablo) => createServer(async (istek, yanit) => { const yol = new URL(istek.url, "http://yerel").pathname; let govde; if (yol === "/rpc") { const { yordam, no } = JSON.parse(await govdeOku(istek)); govde = YORDAM[yordam]?.(tablo[no]) ?? { hata: "bilinmeyen yordam" }; } else if (yol === "/sorgu") { const { no, alanlar } = JSON.parse(await govdeOku(istek)); govde = Object.fromEntries(alanlar.map((a) => [a, tablo[no][a]])); } else { govde = tablo[yol.split("/").pop()] ?? { hata: "bulunamadi" }; } const metin = JSON.stringify(govde); yanit.writeHead(200, { "content-type": "application/json" }).end(metin); }).listen(port, "127.0.0.1", () => console.log(`${ad} 127.0.0.1:${port}`)); sun(8471, "teslimat-op ", GONDERI); sun(8472, "ucretlendirme", UCRET);
Ölçüm ağ geçidinin yerini alır: her biçimde aynı takip yanıtını kurar ve dört sayı toplar. Bayt sayıları yalnız gövdeyi sayar; başlık ve protokol yükü K01’in hesabında da dışarıda bırakılmıştı. Ad sayısı, çağıranın kodunda geçen karşı taraf adlarıdır — yol adı, yordam adı ve okunan alan adı. Servis adları üç biçimde de aynıdır ve önceki dersin keşif katmanından gelir, bu yüzden sayılmaz.
// iletisim/olc.mjs — ayni ic cagriyi uc bicimde olcer, sonra K01'in tepe okuma hizina uygular const OKUNAN = ["durum", "bolge", "guncellenme", "rota", "net"]; // gecidin yanittan okudugu alanlar let cagri = 0, gonderilen = 0, alinan = 0; async function cagir(port, yol, govde) { cagri += 1; const metin = govde === undefined ? undefined : JSON.stringify(govde); if (metin) gonderilen += Buffer.byteLength(metin); const y = await fetch(`http://127.0.0.1:${port}${yol}`, metin ? { method: "POST", body: metin } : {}); const cevap = await y.text(); alinan += Buffer.byteLength(cevap); return JSON.parse(cevap); } const sifirla = () => { cagri = gonderilen = alinan = 0; }; const BICIM = { "kaynak temelli": { yol: ["/gonderi", "/ucret"], yordam: [], calis: async (n) => [await cagir(8471, `/gonderi/${n}`), await cagir(8472, `/ucret/${n}`)] }, "uzak yordam": { yol: ["/rpc"], yordam: ["takipOzeti", "netUcret"], calis: async (n) => [await cagir(8471, "/rpc", { yordam: "takipOzeti", no: n }), await cagir(8472, "/rpc", { yordam: "netUcret", no: n })] }, "sorgu temelli": { yol: ["/sorgu"], yordam: [], calis: async (n) => [await cagir(8471, "/sorgu", { no: n, alanlar: OKUNAN.slice(0, 4) }), await cagir(8472, "/sorgu", { no: n, alanlar: ["net"] })] }, }; const OLCU = ["ic cagri", "gonderilen bayt", "alinan bayt", "toplam ic bayt", "cagiranin bildigi ad", " yol adi", " yordam adi", " alan adi"]; const sonuc = []; for (const [ad, b] of Object.entries(BICIM)) { sifirla(); const [a, c] = await b.calis("TR-4821"); const okunan = OKUNAN.filter((k) => a[k] !== undefined || c[k] !== undefined).length; sonuc.push([ad, { "ic cagri": cagri, "gonderilen bayt": gonderilen, "alinan bayt": alinan, "toplam ic bayt": gonderilen + alinan, " yol adi": b.yol.length, " yordam adi": b.yordam.length, " alan adi": okunan, "cagiranin bildigi ad": b.yol.length + b.yordam.length + okunan }]); } console.log(`${"olcu".padEnd(22)}${sonuc.map(([a]) => a.padStart(16)).join("")}`); for (const o of OLCU) console.log(`${o.padEnd(22)}${sonuc.map(([, s]) => String(s[o]).padStart(16)).join("")}`); // K01 Kabaca Buyukluk Hesabi: tepe okuma 416.67 istek/s; K02 ag gecidi toplamasi bu hizi koruyor const OKUMA_TEPE = 416.67, V5 = 480, K01_CIKIS = 1.6; console.log(`\n${"bicim".padEnd(22)}${"ic istek/s".padStart(12)}${"ic sinir Mbit/s".padStart(17)}` + `${"K01 okuma cikisina oran".padStart(25)}`); for (const [ad, s] of sonuc) { const mbit = (OKUMA_TEPE * s["toplam ic bayt"] * 8) / 1e6; console.log(`${ad.padEnd(22)}${(OKUMA_TEPE * s["ic cagri"]).toFixed(2).padStart(12)}` + `${mbit.toFixed(3).padStart(17)}${(mbit / K01_CIKIS).toFixed(2).padStart(25)}`); } const kaynak = sonuc[0][1]["toplam ic bayt"], yordam = sonuc[1][1]["toplam ic bayt"]; console.log(`kaynak temelli / uzak yordam bayt orani = ${(kaynak / yordam).toFixed(2)};` + ` K01'in disa verdigi takip yaniti ${V5} bayt (V5)`);
node iletisim/servis.mjs & p=$! curl -s --retry 20 --retry-connrefused --retry-delay 0 -o /dev/null http://127.0.0.1:8472/ucret/TR-4821 node iletisim/olc.mjs kill $p
teslimat-op 127.0.0.1:8471 ucretlendirme 127.0.0.1:8472 olcu kaynak temelli uzak yordam sorgu temelli ic cagri 2 2 2 gonderilen bayt 0 74 99 alinan bayt 352 107 107 toplam ic bayt 352 181 206 cagiranin bildigi ad 7 8 6 yol adi 2 1 1 yordam adi 0 2 0 alan adi 5 5 5 bicim ic istek/s ic sinir Mbit/s K01 okuma cikisina oran kaynak temelli 833.34 1.173 0.73 uzak yordam 833.34 0.603 0.38 sorgu temelli 833.34 0.687 0.43 kaynak temelli / uzak yordam bayt orani = 1.94; K01'in disa verdigi takip yaniti 480 bayt (V5)
Değişmeyen Sayı
Tablonun ilk satırı üç kolonda da 2. Bu, dersin en önemli sonucudur: çağrı biçimi iç çağrı sayısını değiştirmiyor. İki çağrı yapılmasının nedeni protokol değil, verinin iki ayrı bağlamda durmasıdır — durum teslimat operasyonunda, tutar ücretlendirmede. Biçim seçimi bu bölünmeyi ne kurar ne kaldırır.
Sayının önemi bir sonraki derste ortaya çıkacak: zincirdeki adım sayısı gecikme bütçesinin bölüneceği parça sayısıdır ve o sayı burada, alan bölünmesiyle belirlenmiştir. Bir biçim seçerek küçültülemez.
Bayt ve Ad
İkinci grup satır iki ölçüyü karşı karşıya koyuyor ve ikisi ters yönde hareket ediyor.
Bayt. Kaynak temelli biçim 352 bayt taşıyor, uzak yordam 181, sorgu temelli 206. Kaynak temelli biçim iki tam kaydı getiriyor: taşıyıcı, ağırlık, hacim, çıkış şubesi ve varış şubesi de telde geçiyor, çünkü adres bir kayda karşılık gelir. Uzak yordam biçiminde sunucu yanıtı çağrının amacına göre sabitlemiş; sorgu temelli biçim aynı alanları getiriyor ama istenen alan adları istekte de yazıldığı için gönderilen bayt 99’a çıkıyor. Oran 1,94: aynı iş, iki katına yakın bayt.
Ad. Çağıranın bilmek zorunda olduğu ad sayısı sorgu temelli biçimde 6, kaynak temelli biçimde
7, uzak yordam biçiminde 8. Sıralama bayt sıralamasıyla aynı değil. Uzak yordam biçimi en az baytı
taşıyor ama en çok adı bilmeyi gerektiriyor, çünkü alan adlarının üstüne bir de yordam adı katmanı
ekliyor: takipOzeti ve netUcret çağıranın koduna yazılmış iki addır ve ikisi de değişebilir.
Ad sayısı bir bağ ölçüsüdür ve bir sonraki dersin doğrudan girdisidir: bir adın değişmesi, o adı
okuyan her tüketicinin değişmesi demektir. Ama adların sahibi de sayılmalıdır. Kaynak temelli
biçimdeki beş alan adı kaydın kendisine aittir ve bütün tüketiciler tarafından paylaşılır;
takipOzeti yordamı ise tek bir çağıran için yazılmıştır. Aynı sayıda ad, değiştirilmesi aynı
zorlukta olmayabilir.
Hesaba Geri Dönüş
Alttaki tablo ölçülen baytı K01’in hızına bağlıyor. Girdiler: tepe okuma 416,67 istek/s (K01) ve ağ geçidinin toplama kararı, ki o karar dış istek hızını değiştirmiyordu (K02).
İç istek hızı üç biçimde de 833,34 istek/s — dış hızın iki katı, çünkü her dış istek iki iç çağrı doğuruyor. Bu sayı K01’in tablosunda yoktu; K01 uçtaki hızı sayıyordu, uygulamanın kendi içindeki çağrıları değil. Servis bölünmesinin sistem üzerindeki ilk sonucu budur: iç istek hızı dış istek hızından bağımsız bir sayıdır ve bölünmeyle çarpılır.
İç sınır bant genişliği kaynak temelli biçimde 1,173 Mbit/s, uzak yordam biçiminde 0,603, sorgu temelli biçimde 0,687. Karşılaştırma noktası K01’in okuma çıkışıdır: 1,60 Mbit/s. Yani iç sınırdan geçen trafik, en pahalı biçimde bile dışa verilen trafiğin 0,73 katında kalıyor. Sayı iki şey söylüyor. Birincisi, iki servisin arasındaki bant genişliği bu ölçekte bir kısıt değildir; biçim seçimi bayta bakılarak yapılamaz. İkincisi, oran ölçekle büyür — bölünme derinleşip her dış istek dört ya da altı iç çağrı doğurduğunda iç trafik dış trafiği geçer ve o noktada aynı tablo başka bir karar verdirir.
Özet
- Üç biçim Web API Tasarımı kursunda istemci sınırında karşılaştırılmıştı; servis sınırında iki uç da bizim olduğu için ölçüler değişir: iç çağrı sayısı, iç bayt ve çağıranın bildiği ad sayısı.
- İç çağrı sayısı üç biçimde de 2 çıktı: çağrı sayısını belirleyen şey protokol değil, verinin iki ayrı bağlamda durmasıdır.
- İç bayt kaynak temelli biçimde 352, uzak yordamda 181, sorgu temellide 206; oran 1,94 ve farkın kaynağı adresin bir kayda karşılık gelmesidir.
- Çağıranın bildiği ad sorgu temellide 6, kaynak temellide 7, uzak yordamda 8; uzak yordam en az baytı taşırken en çok adı gerektiriyor, çünkü alan adlarına bir yordam adı katmanı ekliyor.
- Adların sayısı kadar sahibi de önemlidir: kayıt alanları bütün tüketicilerle paylaşılır, amaca özel bir yordam adı tek çağırana aittir.
- K01’e dönüş: iç istek hızı 833,34 istek/s (dış hızın iki katı) ve iç sınır 0,603–1,173 Mbit/s, yani K01’in 1,60 Mbit/s’lik okuma çıkışının 0,38–0,73 katı; oran bölünme derinleştikçe büyür.
Sonraki Adım
Bu ders çağıranın bilmek zorunda olduğu adları saydı ve sayının altı ile sekiz arasında değiştiğini gösterdi. Sayının kendisi tek başına bir şey söylemez; anlamı, o adlardan biri değiştiğinde ortaya çıkar. Ağ geçidi tek çağıran değildir: aynı iki servisi gün sonu ücretlendirme işi, ön yüz için kurulan arayüz ve rapor akışı da çağırır ve her biri farklı bir alan altkümesi okur. Sonraki ders bir alan adı değiştiğinde kaç tüketicinin kırıldığını sayar, aynı değişikliğin sıraya bölünerek kırılan tüketici sayısının sıfıra indirilebildiğini gösterir ve bunun geçiş penceresinde iç sınıra ne ödettiğini hesaplar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.