Ders 09 / 30
Dış Erişim
Kümenin dışına açılan yolun iki ölçüsü: dış dengeleyici, giriş kuralı, servis nesnesi ve kapsülden oluşan dört katmanın eklediği tur ile taranan kural sayısı, ve yol tabanlı ile ad tabanlı yönlendirmenin dış uç, kimlik kalemi ve toplam yüzey cinsinden farkı.
İçindekiler
Önceki dersin bütün istekleri kümenin içinden geldi. Doğrulayıcı, aynı kümedeki okuma toplayıcıyı adıyla çağırdı; ad çözümlemesi de dönüşümlü dağıtım da o sınırın içinde çalıştı. Bölgesel ölçüm ağının faturalama arayüzüne gelen istek ise dışarıdandır — kümeyi bilmeyen, servis adını çözemeyen, uç nokta listesini görmeyen bir istemciden. Bu isteğin bir kapsüle ulaşması için aradaki mesafenin nesnelerle döşenmesi gerekir.
Döşenen nesne giriş kuralıdır: dışarıdaki bir adı ve yolu, içerideki bir servis nesnesine bağlayan bir eşleşme listesi. Tek başına yetmez; kuralın dinlediği bir dış uç ve o ucun arkasında duran bir yük dengeleyici de gerekir. Bu ders o zinciri katman katman sayar ve iki yönlendirme biçimini karşılaştırır. Yapılandırma örnekleri kendi küçük şemamızla yazılmıştır; ölçülen şey bir modeldir, gerçek bir küme koşturulmaz.
TN19 — bölgesel ölçüm ağının dışa açık arayüzleri on ikiye kadar sayılır, hepsi kurgudur. TN20 — dışarıdan gelen istek dört katmandan geçer: dış yük dengeleyici, giriş kuralı, servis nesnesi, kapsül. TN21 — her katman bir tur ekler; dengeleyici ile giriş kuralı ayrıca kendi listelerini sırayla tarar. TN22 — yol tabanlı yönlendirmede bütün servisler tek bir dış ucun arkasındadır, ad tabanlı yönlendirmede her servisin kendi dış ucu vardır. TN23 — her dış uç bir kimlik kalemi ve bir dengeleyici kaydı ister. TN24 — kural listesi sırayla taranır ve ilk eşleşme kazanır; en uzun önek kuralı kendiliğinden uygulanmaz.
Dört Katman ve Dışa Açılan Yüzey
Aşağıdaki model önce tek bir isteğin katmanlarını, sonra üç farklı servis sayısında iki yönlendirme biçiminin dışarıya ne kadar yüzey açtığını sayıyor.
// dis-erisim.mjs — disaridan gelen istegin katmanlari ve disa acilan yuzey (MODEL). // Giris kuralinin semasi burada tanimlidir: her kural bir (ana, yol) ciftini bir servise baglar. export const SEMA = { ana: 'metin', yol: 'metin', servis: 'metin', kapi: 'sayi' }; export const SERVISLER = ['faturalama', 'is-emri', 'olcum-raporu', 'sayac-kayit', 'abone-arayuzu', 'kesinti-bildirimi', 'tarife-sorgu', 'borc-sorgu', 'tahsilat', 'ariza-kaydi', 'sozlesme', 'tuketim-gecmisi']; // TN19: disa acik kurgu arayuzler export function kurallar(n, bicim) { return SERVISLER.slice(0, n).map((s) => (bicim === 'ad' ? { ana: `${s}-disa`, yol: '/', servis: s, kapi: 8080 } : { ana: 'olcum-disa', yol: `/${s}`, servis: s, kapi: 8080 })); } // Disa acilan yuzey: kac dis uc, kac yol, uc basina bir kimlik kalemi (TN22, TN23). export function yuzey(n, bicim) { const k = kurallar(n, bicim); const uc = new Set(k.map((x) => x.ana)).size; const yol = new Set(k.map((x) => `${x.ana}${x.yol}`)).size; return { uc, kural: k.length, yol, kimlik: uc, toplam: uc + yol + uc }; } // TN20-TN21: dort katman, her biri bir tur; taranan kural sayisi katmana gore degisir. export function katmanlar(n, bicim) { const y = yuzey(n, bicim); return [ ['dis dengeleyici', 1, (y.uc + 1) / 2], ['giris kurali', 1, bicim === 'ad' ? 1 : (y.kural + 1) / 2], ['servis nesnesi', 1, 1], ['kapsul', 1, 0], ]; } if (import.meta.url === `file://${process.argv[1]}`) { const s = (x, n) => String(x).padStart(n); const N = 6; console.log(`${N} disa acik servis, kural semasi: ${Object.keys(SEMA).join(', ')}`); console.log(`${'katman'.padEnd(18)}${s('tur', 5)}${s('yol tabanli taranan', 21)}` + `${s('ad tabanli taranan', 20)}`); const yolK = katmanlar(N, 'yol'), adK = katmanlar(N, 'ad'); const top = (k, i) => k.reduce((a, x) => a + x[i], 0); for (let i = 0; i < yolK.length; i++) { console.log(`${yolK[i][0].padEnd(18)}${s(yolK[i][1], 5)}${s(yolK[i][2], 21)}` + `${s(adK[i][2], 20)}`); } console.log(`${'toplam'.padEnd(18)}${s(top(yolK, 1), 5)}${s(top(yolK, 2), 21)}` + `${s(top(adK, 2), 20)}`); console.log(`\n${'servis'.padEnd(8)}${'bicim'.padEnd(12)}${s('dis uc', 8)}${s('kural', 7)}` + `${s('disa acik yol', 15)}${s('kimlik kalemi', 15)}${s('yuzey kalemi', 14)}`); for (const n of [3, 6, 12]) { for (const b of ['yol', 'ad']) { const y = yuzey(n, b); console.log(`${String(n).padEnd(8)}${(b === 'yol' ? 'yol tabanli' : 'ad tabanli').padEnd(12)}` + `${s(y.uc, 8)}${s(y.kural, 7)}${s(y.yol, 15)}${s(y.kimlik, 15)}${s(y.toplam, 14)}`); } } }
6 disa acik servis, kural semasi: ana, yol, servis, kapi katman tur yol tabanli taranan ad tabanli taranan dis dengeleyici 1 1 3.5 giris kurali 1 3.5 1 servis nesnesi 1 1 1 kapsul 1 0 0 toplam 4 5.5 5.5 servis bicim dis uc kural disa acik yol kimlik kalemi yuzey kalemi 3 yol tabanli 1 3 3 1 5 3 ad tabanli 3 3 3 3 9 6 yol tabanli 1 6 6 1 8 6 ad tabanli 6 6 6 6 18 12 yol tabanli 1 12 12 1 14 12 ad tabanli 12 12 12 12 36
Birinci tablo iki şey söylüyor. Birincisi katman sayısıdır: dışarıdan gelen bir istek kapsüle varmadan önce dört durak geçer ve dördü de bir tur eder. Bu dört tur, istemcinin ödediği sabit bedeldir; küme içindeki bir çağrının ödediği tur sayısıyla kıyaslandığında fark, kümenin dışında olmanın fiyatıdır.
Bu dört turun ne kadar olduğu ancak bir karşılaştırmayla anlaşılır. Önceki dersteki küme içi çağrı iki tur ediyordu: bir ad çözümleme turu ve isteğin kendisi. Dışarıdan gelen istek dört tur öder, yani iki katı; aradaki iki tur dengeleyici ile giriş kuralının payıdır. Bu iki katman kaldırılıp kapsüller doğrudan dışarı açılsaydı fark kapanırdı — ama o zaman dışa açılan yüzey kapsül sayısı kadar olurdu ve kapsüller devir hâlindeyken adresleri de değişirdi. İki katman, önceki iki dersin kurduğu kararlılığın dışarıya taşınmasının bedelidir.
İkincisi daha ilginçtir: toplam taranan kural iki biçimde de aynıdır — beş buçuk. Yol tabanlıda dengeleyici tek kayıt tutar, giriş kuralı altı kuralı tarar; ad tabanlıda dengeleyici altı kaydı tarar, giriş kuralı bir kuralla eşleşir. Ayrım bir tasarruf değil, bir yer değiştirmedir: aynı iş bir katmandan ötekine taşınır. Bu, ölçmeden verilen “ad tabanlı daha hızlıdır” türü kararların neden dayanaksız olduğunu gösteriyor.
Gerçek fark ikinci tablodadır ve tur değil yüzeydir. Üç serviste iki biçim arasındaki fark beşe dokuzdur; altı serviste sekize on sekiz, on iki serviste on dörde otuz altı. Yol tabanlı biçimde dış uç sayısı servis sayısından bağımsızdır, hep birdir; ad tabanlı biçimde servis sayısı kadardır. Kimlik kalemi de uca bağlı olduğu için aynı oranda büyür. On iki servis dışarı açıldığında yol tabanlı biçim on dört, ad tabanlı biçim otuz altı kalem yönetmeyi gerektirir — iki buçuk katı.
Kural sayısının iki biçimde de eşit olması bu tablonun ikinci sonucudur. Kural sayısı servis sayısına eşittir ve yönlendirme biçiminden bağımsızdır. Değişen, kuralların kaç ayrı dış uca dağıldığıdır. Bu yüzden “kaç kural yazılacak” sorusu biçim seçiminde bir ölçüt değildir; “kaç uç korunacak” sorusu ölçüttür.
Kuralın Sırası
Kural sayısını bilmek yönlendirmenin doğru olacağını göstermez. TN24 kural listesinin sırayla tarandığını ve ilk eşleşmenin kazandığını söyler; iç içe yollar bu kuralla birleştiğinde sıra bir ayrıntı olmaktan çıkar.
// yonlendirme.mjs — kural sirasinin yonlendirme kararina etkisi (MODEL). import { SEMA } from './dis-erisim.mjs'; // Ayni sema, ic ice yollarla: alt yol kendi servisine gitmelidir. const KURALLAR = [ { ana: 'olcum-disa', yol: '/fatura', servis: 'faturalama', kapi: 8080 }, { ana: 'olcum-disa', yol: '/fatura/dokum', servis: 'fatura-dokum', kapi: 8080 }, { ana: 'olcum-disa', yol: '/is-emri', servis: 'is-emri', kapi: 8080 }, { ana: 'olcum-disa', yol: '/is-emri/acil', servis: 'acil-is-emri', kapi: 8080 }, { ana: 'olcum-disa', yol: '/rapor', servis: 'olcum-raporu', kapi: 8080 }, { ana: 'olcum-disa', yol: '/rapor/aylik', servis: 'aylik-rapor', kapi: 8080 }, ]; // Beklenen sonuc: en uzun onek kazanir. Bu beklenti kuralda yazili degildir. const ISTEKLER = [ ['/fatura', 'faturalama'], ['/fatura/dokum', 'fatura-dokum'], ['/fatura/dokum/2026', 'fatura-dokum'], ['/is-emri', 'is-emri'], ['/is-emri/acil', 'acil-is-emri'], ['/is-emri/acil/12', 'acil-is-emri'], ['/rapor', 'olcum-raporu'], ['/rapor/aylik', 'aylik-rapor'], ['/rapor/aylik/03', 'aylik-rapor'], ['/rapor/gunluk', 'olcum-raporu'], ['/abone', null], ['/', null], ]; // TN24: kural listesi sirayla taranir, ilk eslesme kazanir. function eslestir(kurallar, yol) { for (let i = 0; i < kurallar.length; i++) { const k = kurallar[i]; if (yol === k.yol || yol.startsWith(`${k.yol}/`)) return { servis: k.servis, taranan: i + 1 }; } return { servis: null, taranan: kurallar.length }; } const SIRALAR = { 'bildirim sirasi': KURALLAR, 'ozgulluk sirasi': [...KURALLAR].sort((a, b) => b.yol.length - a.yol.length), }; const s = (x, n) => String(x).padStart(n); console.log(`${KURALLAR.length} kural, ${ISTEKLER.length} istek, sema: ${Object.keys(SEMA).join(', ')}`); console.log(`${'kural sirasi'.padEnd(18)}${s('dogru', 7)}${s('yanlis servis', 15)}` + `${s('kural bulunamadi', 18)}${s('ortalama taranan', 18)}`); for (const [ad, kurallar] of Object.entries(SIRALAR)) { let dogru = 0, yanlis = 0, yok = 0, taranan = 0; for (const [yol, beklenen] of ISTEKLER) { const r = eslestir(kurallar, yol); taranan += r.taranan; if (r.servis === null) yok++; if (r.servis === beklenen) dogru++; else if (r.servis !== null) yanlis++; } console.log(`${ad.padEnd(18)}${s(dogru, 7)}${s(yanlis, 15)}${s(yok, 18)}` + `${s((taranan / ISTEKLER.length).toFixed(2), 18)}`); } console.log(`\nbildirim sirasinda yanlis giden istekler:`); for (const [yol, beklenen] of ISTEKLER) { const r = eslestir(SIRALAR['bildirim sirasi'], yol); if (r.servis !== beklenen && r.servis !== null) { console.log(` ${yol.padEnd(20)} -> ${String(r.servis).padEnd(14)} (beklenen ${beklenen},` + ` ${r.taranan}. kuralda esletti)`); } }
6 kural, 12 istek, sema: ana, yol, servis, kapi kural sirasi dogru yanlis servis kural bulunamadi ortalama taranan bildirim sirasi 6 6 2 3.67 ozgulluk sirasi 12 0 2 3.75 bildirim sirasinda yanlis giden istekler: /fatura/dokum -> faturalama (beklenen fatura-dokum, 1. kuralda esletti) /fatura/dokum/2026 -> faturalama (beklenen fatura-dokum, 1. kuralda esletti) /is-emri/acil -> is-emri (beklenen acil-is-emri, 3. kuralda esletti) /is-emri/acil/12 -> is-emri (beklenen acil-is-emri, 3. kuralda esletti) /rapor/aylik -> olcum-raporu (beklenen aylik-rapor, 5. kuralda esletti) /rapor/aylik/03 -> olcum-raporu (beklenen aylik-rapor, 5. kuralda esletti)
Aynı altı kural, aynı on iki istek, iki farklı sıra: on iki doğru ya da altı doğru. Bildirim sırasında yazılan liste okunduğunda hiçbir şey yanlış görünmez — her servisin kendi satırı vardır ve her satır doğrudur. Yanlış olan satırların arasındaki ilişkidir ve bu ilişki dosyada hiçbir yerde yazılı değildir. Alt yolun kendi servisine gitmesi gerektiği bir beklentidir; kural listesi bu beklentiyi değil, yalnız sırayı bilir.
Alttaki dökümün son sütunu yanlışın nasıl oluştuğunu gösteriyor: altı isteğin hepsi de daha genel kuralla eşleşiyor ve eşleşme birinci, üçüncü ve beşinci kuralda gerçekleşiyor. Daha özgül kural listede hemen bir alttadır ve hiç okunmaz. Bu yüzden ortalama taranan kural sayısı yanlış sırada daha düşüktür — üç virgül altmış yediye karşı üç virgül yetmiş beş. Yanlış yönlendirme daha az iş yaparak elde edilir; hızlı olan yanıt doğru olan yanıt değildir.
Bu koşum, ad tabanlı biçimin ne kazandırdığını da geriye dönük olarak söylüyor. Her servisin kendi dış ucu olduğunda o ucun kural listesinde tek bir satır bulunur; iki kuralın birbirini kapsaması diye bir durum doğmaz ve buradaki altı yanlış yönlendirme oluşamaz. Otuz altı yüzey kaleminin karşılığı budur: yönlendirme kararının, kuralların sırasına bağlı olmaktan çıkması. İki biçim arasındaki seçim, yönetilecek nesne sayısı ile bir yanlış karar sınıfının varlığı arasında yapılıyor.
İki satırda da eşleşmeyen istek sayısı ikidir ve bu iki istek bir hata değildir. /abone ile /
için dışa açılan yüzeyde bir kural yoktur, dolayısıyla giriş kuralı bir karar veremez ve isteği
reddeder. Dışa açık yüzeyin sayılabilir olmasının anlamı budur: yüzeyde olmayan bir yol, kümenin
içine hiçbir yoldan giremez.
Devredilen Karar ve Bilmediği Şey
Bu derste devredilen karar dışarıdan gelen isteğin hangi iç servise gideceğidir. Bu karar istemcide de verilebilirdi — her arayüz için ayrı bir adres, istemcinin yapılandırmasında. Giriş kuralı o kararı kümeye taşır ve karşılığında dört bilgi kalemi ister: dış ad, yol, hedef servis adı, hedef kapı. Dört kalemin dördü de bildirimdir; ölçüm gerektirmez, eskimez.
Maliyet bildirimin kendisinde değil, sayısında ve sırasındadır. İkinci tablo sayının nasıl büyüdüğünü gösterdi: on iki servis, ad tabanlı biçimde otuz altı yüzey kalemi eder ve bunların on ikisi kimlik kalemidir; her biri süresi dolan, yenilenmesi gereken bir nesnedir. Yol tabanlı biçimde aynı iş on dört kalemle görülür ve kimlik kalemi tektir. Devretmenin bedeli burada bir gecikme değil, yönetilecek nesne sayısıdır.
Bilinen bir istek kümesinde üç sonuç şöyle sayılıyor. On iki isteğin onu bir kurala uyar, ikisi uymaz. Özgüllük sırasında on doğru karar, sıfır yanlış karar ve iki karar verememe vardır; bildirim sırasında dört doğru, altı yanlış ve yine iki karar verememe. Karar verememe sayısının iki sırada da aynı kalması anlamlıdır: o iki istek yüzeyde karşılığı olmadığı için reddedilir ve bu, sıradan bağımsız bir sonuçtur. Değişen tek şey, uyan on isteğin kaçının doğru yere gittiğidir.
Sistemin bilmediği şey ise ikinci koşumda görüldü: kuralların hangisinin ötekini kapsadığı. Giriş kuralı yollar arasındaki içerme ilişkisini çıkarmaz, listeyi sırayla okur. Bu eksik bilgi altı isteği yanlış servise götürdü ve hiçbirinde bir hata kaydı doğmadı — istekler yanıtlandı, yalnız yanlış yerden. Doğru sıra bir kez yazılınca çalışır, ama bir kural sonradan eklendiğinde aynı bilgi yeniden gerekir. Bir kararı devretmek, o kararın dayandığı ilişkinin her değişiklikte yeniden bildirilmesini zorunlu kılar. Bildirim bir kez yazılıp unutulan bir metin değil, kural kümesi her büyüdüğünde yeniden gözden geçirilmesi gereken bir sıralamadır; altı kuralda gözle görülen bu ilişki, on iki kuralda görünmez olur.
Özet
- Dışarıdan gelen istek dört katmandan geçer — dış dengeleyici, giriş kuralı, servis nesnesi, kapsül — ve her katman bir tur ekler; toplam dört turdur.
- Yol tabanlı ve ad tabanlı yönlendirmede toplam taranan kural sayısı aynıdır (beş buçuk); ayrım bir tasarruf değil, işin bir katmandan ötekine taşınmasıdır.
- Kural sayısı servis sayısına eşittir ve biçimden bağımsızdır; değişen, kuralların kaç ayrı dış uca dağıldığıdır.
- Dışa açılan yüzey üç serviste beşe dokuz, altı serviste sekize on sekiz, on iki serviste on dörde otuz altıdır; ad tabanlı biçimde dış uç ve kimlik kalemi servis sayısıyla birlikte büyür.
- Aynı altı kural, bildirim sırasında on iki isteğin altısını yanlış servise gönderdi; özgüllük sırasında hepsi doğru gitti. Yanlış eşleşmeler daha az kural tarayarak, yani daha hızlı oluştu.
- Giriş kuralı dört bildirim kalemi ister ve hiçbiri eskimez; bilmediği tek şey kurallar arasındaki kapsama ilişkisidir ve bu ilişki her yeni kuralda yeniden bildirilmelidir.
Sonraki Adım
Bu ders isteği kapsülün kapısına kadar getirdi. İçeride çalışan sürecin ise kapıya gelen istekten başka ihtiyaçları vardır: hangi veri deposuna bağlanacağı, hangi eşiklerle çalışacağı, hangi anahtarla kimlik doğrulayacağı. Bu değerler imajın içine yazılırsa üç ortam üç ayrı imaj demektir; dışarıda tutulursa kümeye bildirilen yeni bir nesne demektir. Sonraki ders bu nesneleri ölçer: aynı ayar kümesi iki farklı biçimde geçirildiğinde değişikliğin koşan kapsüle ne zaman yansıdığı, kaç anahtarın hangi biçimde taşındığı ve gizli tutulması gereken değerlerin küme içinde kaç özneye görünür olduğu.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.