İçeriğe geç
academia.sh

Ders 19 / 20

Bağlamalar ve Servis Bağlantıları

Aynı kaynağa çalışma zamanında istemci kurarak ve bildirimsel bağlamayla erişilir; kod satırı, açılış işi, kimlik bilgisinin yeri ve hatanın görülme anı sayılır. Bağlamanın kapsam ve taşınabilirlik kısıtları da ölçülür.

İçindekiler

Bir önceki ders kenarda kuyruk ve zamanlayıcı kullandı, ama bu kaynaklara erişimin nasıl kurulduğunu hiç sormadı. İki yol vardır. Birincisinde işlev açılırken kaynağın adresini, kimlik bilgisini ve ayarlarını okur, bir istemci kurar ve bağlanır. İkincisinde dağıtım tanımına bir bağlama yazılır ve çalışma zamanı işleve hazır bir kol verir. Bu ders aynı beş kaynağa iki yoldan erişip dördünü sayar: kod satırı, açılış işi, kimlik bilgisinin nerede durduğu, ve yanlış yapılandırmanın ne zaman fark edildiği.

Kaynağın nasıl yaratıldığı bu dersin konusu değildir; sağlayıcı arayüzü ve kaynak alanları kod olarak altyapı kursunda ölçüldü. Buradaki soru sonrasıdır: çalışan koda o kaynak nasıl bağlanıyor. Ölçüm yine bölgesel ölçüm ağı üzerindedir ve kurgudur; katalog, istemci ve bağlama kolu node ile kurulmuş bir modeldir.

KE31. Kurgu katalogda dokuz kaynak ve dokuz tür vardır; her tür için istemcinin kurması gereken alanlar yazılıdır. KE32. Bildirimsel bağlama bu türlerden yalnız beşini destekler; kalan dördü çalışma zamanında istemci kurularak erişilir. KE33. İstemci yolu açılışta bütün bağlantıları kurar ve her bağlantının sabit bir kurma süresi vardır; bağlama yolu açılışta hiçbir bağlantı kurmaz, kol ilk kullanımda bağlanır. KE34. Kenar çalışma zamanının soğuk başlangıç tabanı 12 ms’dir; açılışta yapılan iş bu tabanın üstüne eklenir. KE35. Kimlik bilgisi istemci yolunda süreç ortamına yazılır ve ayar nesnesinden istemciye geçer; bağlama yolunda koda hiç girmez. Metinde geçen gizli değer kurgu bir yer tutucudur. KE36. Dağıtım anında bir doğrulayıcı manifestoyu katalogla karşılaştırıp yapısal hataları yakalar; istemci yolunda böyle bir doğrulama yoktur, hata kaynağa ilk çağrıda görülür.

Aynı Kaynak, İki Erişim Yolu

// kaynak.mjs — kurgu kaynak katalogu, iki erisim yolu ve kimlik tarayicisi (model).
export const TURLER = {                             // istemcinin kurmasi gereken alanlar
  veri_deposu:  { alan: ["adres", "kimlik", "zaman_asimi", "deneme", "havuz"], baglanabilir: true },
  kuyruk:       { alan: ["adres", "kimlik", "zaman_asimi", "toplu"], baglanabilir: true },
  nesne_deposu: { alan: ["adres", "kimlik", "bolge", "zaman_asimi"], baglanabilir: true },
  anahtar_deger:{ alan: ["adres", "kimlik", "zaman_asimi"], baglanabilir: true },
  konu:         { alan: ["adres", "kimlik", "zaman_asimi"], baglanabilir: true },
  iliskisel:    { alan: ["adres", "kimlik", "zaman_asimi", "havuz", "sema"], baglanabilir: false },
  dis_servis:   { alan: ["adres", "kimlik", "zaman_asimi", "deneme"], baglanabilir: false },
  dizin:        { alan: ["adres", "kimlik", "zaman_asimi"], baglanabilir: false },
  akis:         { alan: ["adres", "kimlik", "bolge", "zaman_asimi", "toplu"], baglanabilir: false },
};
export const KAYNAKLAR = [                          // acilis: baglanti kurma ms; ilk: dagitimdan ilk cagriya dk
  { ad: "olcum_deposu", tur: "veri_deposu", acilis: 34, ilk: 0.2 },
  { ad: "sayac_kuyrugu", tur: "kuyruk", acilis: 21, ilk: 0.2 },
  { ad: "arsiv_deposu", tur: "nesne_deposu", acilis: 27, ilk: 540 },
  { ad: "oran_sayaci", tur: "anahtar_deger", acilis: 8, ilk: 0.2 },
  { ad: "bildirim_konusu", tur: "konu", acilis: 15, ilk: 47 },
  { ad: "fatura_tablosu", tur: "iliskisel", acilis: 52, ilk: 540 },
  { ad: "saha_gecidi", tur: "dis_servis", acilis: 19, ilk: 47 },
  { ad: "kimlik_dizini", tur: "dizin", acilis: 23, ilk: 0.2 },
  { ad: "rapor_akisi", tur: "akis", acilis: 30, ilk: 540 },
];
export const BAGLANABILIR = KAYNAKLAR.filter((k) => TURLER[k.tur].baglanabilir);
export const SOGUK_TABAN = 12;                      // soguk baslangic tabani, ms
export const GIZLI = "KURGU-GIZLI-DEGER";           // kurgu yer tutucu; gercek bir kimlik bilgisi degil

export const istemciKodu = (k) => [                 // calisma zamaninda istemci kurma kodu
  `const ${k.ad}_ayar = {`,
  ...TURLER[k.tur].alan.map((a) => `  ${a}: ortam("${k.ad.toUpperCase()}_${a.toUpperCase()}"),`),
  `};`,
  `const ${k.ad} = istemciKur("${k.tur}", ${k.ad}_ayar);`,
  `await ${k.ad}.baglan();`,
];
export const baglamaSatiri = (k) => [`  { ad: "${k.ad}", tur: "${k.tur}", hedef: "${k.ad}-uretim" },`];
export const ORTAK = 12;                            // yardimci islevlerin satiri
export const SARMAL = 2;                            // manifestonun acilis ve kapanis satiri

export function istemciKur(tur, ayar) {             // kimlik ayar nesnesinde ve istemcide durur
  return { tur, ayar, baglan: () => true, cagir: (n) => `${tur}:${n}` };
}
export function baglamaKolu(k) {                    // baglama kolu: kimlik alani hic yok
  return { ad: k.ad, tur: k.tur, cagir: (n) => `${k.tur}:${n}` };
}
export function tara(nesne, yol = "kok", bulgu = []) {   // nesne grafinde kimlik alani arar
  for (const [a, d] of Object.entries(nesne)) {
    if (a === "kimlik") bulgu.push(`${yol}.${a}`);
    else if (d && typeof d === "object") tara(d, `${yol}.${a}`, bulgu);
  }
  return bulgu;
}
export function uretec(tohum) {                     // tohum gorunur; kosumdan kosuma ayni dizi
  let s = tohum >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296;
}
// kod.mjs — ayni bes kaynak iki yolla: kod satiri ve acilis isi sayilir.
import { TURLER, KAYNAKLAR, BAGLANABILIR, SOGUK_TABAN, istemciKodu, baglamaSatiri,
  ORTAK, SARMAL, uretec } from "./kaynak.mjs";

const sut = (...s) => console.log(s.map((x, i) => String(x).padEnd(i ? 16 : 17)).join("").trimEnd());
sut("kaynak", "tur", "alan", "istemci satiri", "baglama satiri");
for (const k of BAGLANABILIR)
  sut(k.ad, k.tur, TURLER[k.tur].alan.length, istemciKodu(k).length, baglamaSatiri(k).length);
const istemciSatir = BAGLANABILIR.reduce((t, k) => t + istemciKodu(k).length, 0) + ORTAK;
const baglamaSatir = BAGLANABILIR.reduce((t, k) => t + baglamaSatiri(k).length, 0) + SARMAL;
console.log(`toplam: istemci ${istemciSatir} satir (${ORTAK} satir ortak yardimci dahil), ` +
  `baglama ${baglamaSatir} satir (${SARMAL} satir manifesto sarmali dahil); ` +
  `oran ${(istemciSatir / baglamaSatir).toFixed(1)}x\n`);

const acilis = BAGLANABILIR.reduce((t, k) => t + k.acilis, 0);
console.log(`istemci yolu acilista ${BAGLANABILIR.length} baglanti kurar: ${acilis} ms; ` +
  `soguk baslangic ${SOGUK_TABAN} ms -> ${SOGUK_TABAN + acilis} ms`);
console.log(`baglama yolu acilista hicbir baglanti kurmaz: 0 ms; ` +
  `soguk baslangic ${SOGUK_TABAN} ms -> ${SOGUK_TABAN} ms (kol ilk kullanimda baglanir)\n`);

const r = uretec(19870504), SOGUK = 40;             // kirk soguk baslangic
let istemciIs = 0, baglamaIs = 0, dokunan = 0;
for (let i = 0; i < SOGUK; i++) {
  const kume = BAGLANABILIR.filter(() => r() < 0.45);
  istemciIs += acilis;                              // hepsi kurulur, kullanilsin kullanilmasin
  baglamaIs += kume.reduce((t, k) => t + k.acilis, 0);
  dokunan += kume.length;
}
console.log(`${SOGUK} soguk baslangic, dokunulan kaynak ortalamasi ` +
  `${(dokunan / SOGUK).toFixed(2)}/${BAGLANABILIR.length}`);
console.log(`acilista yapilan is: istemci ${istemciIs} ms, baglama ${baglamaIs} ms ` +
  `(${(100 * (istemciIs - baglamaIs) / istemciIs).toFixed(1)}% daha az)`);

const disarida = KAYNAKLAR.filter((k) => !TURLER[k.tur].baglanabilir);
const disSatir = disarida.reduce((t, k) => t + istemciKodu(k).length, 0) + ORTAK;
console.log(`\nbaglamanin kapsami: ${BAGLANABILIR.length}/${KAYNAKLAR.length} kaynak turu; ` +
  `kalan ${disarida.length} kaynak (${disarida.map((k) => k.tur).join(", ")}) istemciyle kurulur`);
console.log(`karisik gercek: ${disSatir} satir istemci kodu ve ` +
  `${disarida.reduce((t, k) => t + k.acilis, 0)} ms acilis isi yerinde kalir`);
kaynak           tur             alan            istemci satiri  baglama satiri
olcum_deposu     veri_deposu     5               9               1
sayac_kuyrugu    kuyruk          4               8               1
arsiv_deposu     nesne_deposu    4               8               1
oran_sayaci      anahtar_deger   3               7               1
bildirim_konusu  konu            3               7               1
toplam: istemci 51 satir (12 satir ortak yardimci dahil), baglama 7 satir (2 satir manifesto sarmali dahil); oran 7.3x

istemci yolu acilista 5 baglanti kurar: 105 ms; soguk baslangic 12 ms -> 117 ms
baglama yolu acilista hicbir baglanti kurmaz: 0 ms; soguk baslangic 12 ms -> 12 ms (kol ilk kullanimda baglanir)

40 soguk baslangic, dokunulan kaynak ortalamasi 2.20/5
acilista yapilan is: istemci 4200 ms, baglama 1936 ms (53.9% daha az)

baglamanin kapsami: 5/9 kaynak turu; kalan 4 kaynak (iliskisel, dis_servis, dizin, akis) istemciyle kurulur
karisik gercek: 45 satir istemci kodu ve 124 ms acilis isi yerinde kalir

Kod satırı ilk ölçüdür. Beş kaynağa istemciyle erişmek 51, bağlamayla erişmek 7 satır tutar. Fark bir biçim tercihi değil, işin nerede yapıldığıdır: istemci yolunda her alan bir satırdır, bağlamada bütün alanlar tek satırın arkasına düşer.

İkinci ölçü açılışta yapılan iştir ve soğuk başlangıca doğrudan eklenir. İstemci yolu açılırken beş bağlantıyı da kurar: 105 milisaniye, yani 12 milisaniyelik taban 117 milisaniyeye çıkar. Bağlama yolu hiçbir bağlantı kurmaz; taban 12 milisaniyede kalır, bağlanma yalnız kol kullanıldığında olur. Kırk soğuk başlangıçlık kurgu trafikte bir çağrı ortalama 2,20 kaynağa dokunur, dolayısıyla bağlama yolu 4200 yerine 1936 milisaniye bağlantı işi yapar: yüzde 53,9 daha az. Fark, istemci yolunun o çağrıda hiç kullanılmayacak bağlantıları da kurmasıdır.

Üçüncü satır kapsamı verir. Bağlama dokuz kaynak türünden beşini tanır; ilişkisel veritabanı, dış servis, dizin ve akış için istemci kurmaktan başka yol yoktur. Bu dört kaynak 45 satır istemci kodunu ve 124 milisaniye açılış işini yerinde tutar.

Kimlik Nerede Durur ve Hata Ne Zaman Görülür

// guven.mjs — kimlik nerede duruyor, hata ne zaman goruluyor, tasima ne tutuyor.
import { TURLER, KAYNAKLAR, BAGLANABILIR, GIZLI, istemciKur, baglamaKolu, tara,
  istemciKodu, baglamaSatiri, ORTAK, SARMAL } from "./kaynak.mjs";

const ortam = {};                                   // kimlik once surec ortamina yazilir
for (const k of BAGLANABILIR) for (const a of TURLER[k.tur].alan)
  ortam[`${k.ad.toUpperCase()}_${a.toUpperCase()}`] = a === "kimlik" ? `${GIZLI}-${k.ad}` : `deger-${a}`;
const istemciler = Object.fromEntries(BAGLANABILIR.map((k) => [k.ad, istemciKur(k.tur,
  Object.fromEntries(TURLER[k.tur].alan.map((a) => [a, ortam[`${k.ad.toUpperCase()}_${a.toUpperCase()}`]])))]));
const kollar = Object.fromEntries(BAGLANABILIR.map((k) => [k.ad, baglamaKolu(k)]));

const say = (m) => (JSON.stringify(m).match(new RegExp(GIZLI, "g")) || []).length;
const sut = (...s) => console.log(s.map((x, i) => String(x).padEnd(i ? 15 : 24)).join("").trimEnd());
sut("kimlik nerede", "istemci", "baglama");
sut("dagitim yapilandirmasi", BAGLANABILIR.length, BAGLANABILIR.length);
sut("surec ortami", Object.values(ortam).filter((v) => v.startsWith(GIZLI)).length, 0);
sut("kod icindeki nesne", tara(istemciler).length, tara(kollar).length);
sut("diziye cevirmede", say(istemciler), say(kollar));
console.log(`taranan alan yollari: ${tara(istemciler).slice(0, 2).join(", ")} ...\n`);

const HATALAR = [                                   // bes kurgu yanlis yapilandirma
  { kaynak: "olcum_deposu", ne: "alan adi yanlis yazildi", yapisal: true },
  { kaynak: "arsiv_deposu", ne: "zorunlu alan verilmedi", yapisal: true },
  { kaynak: "bildirim_konusu", ne: "katalogda olmayan tur", yapisal: true },
  { kaynak: "sayac_kuyrugu", ne: "kaynak adi yanlis", yapisal: true },
  { kaynak: "arsiv_deposu", ne: "baska var olan hedef", yapisal: false },
];
const ilk = (ad) => KAYNAKLAR.find((k) => k.ad === ad).ilk;
const s2 = (...s) => console.log(s.map((x, i) => String(x).padEnd(i ? 17 : 40)).join("").trimEnd());
s2("yanlis yapilandirma", "istemci", "baglama");
for (const h of HATALAR)
  s2(`${h.kaynak}: ${h.ne}`, `${ilk(h.kaynak)} dk sonra`, h.yapisal ? "dagitimda, 0 dk" : `${ilk(h.kaynak)} dk sonra`);
const gec = HATALAR.filter((h) => !h.yapisal);
console.log(`istemci: 0/${HATALAR.length} dagitimda yakalandi, toplam gecikme ` +
  `${HATALAR.reduce((t, h) => t + ilk(h.kaynak), 0).toFixed(1)} dk, en kotusu ${Math.max(...HATALAR.map((h) => ilk(h.kaynak)))} dk`);
console.log(`baglama: ${HATALAR.length - gec.length}/${HATALAR.length} dagitimda yakalandi, ` +
  `kalan ${gec.length} hata ${gec.reduce((t, h) => t + ilk(h.kaynak), 0)} dk sonra\n`);

const STUB = 3;                                     // her kol icin yazilan sahte kol satiri
const degisenIstemci = BAGLANABILIR.reduce((t, k) => t + TURLER[k.tur].alan.length, 0);
const degisenBaglama = BAGLANABILIR.reduce((t, k) => t + baglamaSatiri(k).length, 0) + SARMAL
  + BAGLANABILIR.length * STUB;
console.log(`baska bir hizmete tasima: istemci yolunda 0 kod satiri degisir, ` +
  `${degisenIstemci} yapilandirma degeri degisir`);
console.log(`baglama yolunda ${degisenBaglama} satir degisir: ` +
  `${degisenBaglama - BAGLANABILIR.length * STUB} manifesto satiri hizmete ozgudur, ` +
  `${BAGLANABILIR.length * STUB} satir yerel sinama icin sahte kol`);
console.log(`istemci kodunun ${BAGLANABILIR.reduce((t, k) => t + istemciKodu(k).length, 0) + ORTAK} satiri ` +
  `oldugu gibi tasinir; baglama tanimi tasinmaz`);
kimlik nerede           istemci        baglama
dagitim yapilandirmasi  5              5
surec ortami            5              0
kod icindeki nesne      5              0
diziye cevirmede        5              0
taranan alan yollari: kok.olcum_deposu.ayar.kimlik, kok.sayac_kuyrugu.ayar.kimlik ...

yanlis yapilandirma                     istemci          baglama
olcum_deposu: alan adi yanlis yazildi   0.2 dk sonra     dagitimda, 0 dk
arsiv_deposu: zorunlu alan verilmedi    540 dk sonra     dagitimda, 0 dk
bildirim_konusu: katalogda olmayan tur  47 dk sonra      dagitimda, 0 dk
sayac_kuyrugu: kaynak adi yanlis        0.2 dk sonra     dagitimda, 0 dk
arsiv_deposu: baska var olan hedef      540 dk sonra     540 dk sonra
istemci: 0/5 dagitimda yakalandi, toplam gecikme 1127.4 dk, en kotusu 540 dk
baglama: 4/5 dagitimda yakalandi, kalan 1 hata 540 dk sonra

baska bir hizmete tasima: istemci yolunda 0 kod satiri degisir, 19 yapilandirma degeri degisir
baglama yolunda 22 satir degisir: 7 manifesto satiri hizmete ozgudur, 15 satir yerel sinama icin sahte kol
istemci kodunun 51 satiri oldugu gibi tasinir; baglama tanimi tasinmaz

Birinci tablo kimlik bilgisinin kaç yerde durduğunu sayar ve iki yol tek satırda birleşir: dağıtım yapılandırmasındaki beş kimlik ikisinde de vardır, çünkü erişim yetkisi bir yerde tanımlanmak zorundadır. Ayrılık ondan sonra başlar. İstemci yolunda kimlik süreç ortamına yazılır, oradan ayar nesnesine, oradan istemciye geçer; tarayıcı işlev nesne grafında beş kimlik alanı bulur ve nesne diziye çevrildiğinde değer beş kez görünür. Bağlama yolunda dördü de sıfırdır: kol nesnesinde kimlik diye bir alan yoktur, çağrıyı çalışma zamanı imzalar. Bir kayıt satırı, bir hata dökümü istemci yolunda beş değeri açığa çıkarabilir; bağlama yolunda açığa çıkacak değer yoktur.

İkinci tablo hatanın ne zaman görüldüğünü sayar. Beş kurgu yanlış yapılandırmadan dördü yapısaldır: alan adı yanlış, zorunlu alan eksik, katalogda olmayan tür, yanlış kaynak adı. Bağlama yolunda dağıtım doğrulayıcısı dördünü de sıfırıncı dakikada yakalar. İstemci yolunda hiçbiri yakalanmaz, çünkü doğrulanacak bir bildirim yoktur; her hata kaynağa ilk çağrıldığı anda görülür. Arşiv deposu yalnız gecelik iş sırasında çağrıldığı için oradaki hata dağıtımdan 540 dakika sonra ortaya çıkar — dokuz saat. Beş hatanın toplam gecikmesi istemci yolunda 1127,4 dakika, bağlama yolunda 540 dakikadır.

Beşinci hata iki yolda da geç görülür ve doğrulamanın sınırını çizer: hedef adı geçerli, tür doğru, katalogda karşılığı var — yalnızca yanlış kaynağa işaret ediyor. Dağıtım doğrulayıcısı biçimi denetler, niyeti denetlemez.

Bağlamanın Kısıtı

Son üç satır taşınabilirliği sayar; bağlamanın ikinci kısıtı buradadır. İstemci kodu taşınırken sıfır satırı değişir, yalnız 19 yapılandırma değeri değişir: kod kaynağı adresle ve ayarla tanır, hizmetle değil. Bağlama tanımı ise hizmete özgüdür: 7 manifesto satırının tamamı yeni hizmetin biçimine göre baştan yazılır. Üstüne, kol çalışma zamanınca verildiği için yerel sınamada karşılığı yoktur: beş kol için 15 satırlık sahte kol gerekir. Taşımanın bedeli bağlama yolunda 22 satır, istemci yolunda sıfır satır ve 19 değerdir.

İki kısıt birlikte okunduğunda bağlamanın gerçek kapsamı çıkar. Dokuz kaynağın beşi bağlanır, dördü bağlanmaz; o dördü için 45 satır istemci kodu, 124 milisaniye açılış işi ve süreç içinde duran kimlik bilgileri yerinde kalır. Bağlama kimliği koddan çıkarmaz, kaynakların beş dokuzunda çıkarır. Devredilen karar bağlantı kurmaktır: karşılığında soğuk başlangıçta 105 milisaniye, kodda 44 satır ve hatanın görülmesinde 587 dakika kazanılır, ama kaynak türü seçimi kataloğa, dağıtım tanımı hizmete bağlanır.

Özet

  • Beş kaynağa istemciyle erişim 51 satır, bağlamayla erişim 7 satır tuttu; oran 7,3 kat.
  • İstemci yolu açılışta 5 bağlantıyı kurup soğuk başlangıcı 12 milisaniyeden 117 milisaniyeye çıkardı; bağlama 12 milisaniyede kaldı. Kırk soğuk başlangıçta çağrı başına ortalama 2,20 kaynağa dokunuldu, bağlantı işi 4200 yerine 1936 milisaniye oldu.
  • Kimlik bilgisi istemci yolunda 4 yerde durdu (dağıtım yapılandırması, süreç ortamı, ayar nesnesi, diziye çevrilmiş istemci); bağlamada yalnız dağıtım yapılandırmasında durdu, kodda 0 kez göründü.
  • 5 yanlış yapılandırmanın 4’ü bağlamada dağıtım anında yakalandı; istemcide 0’ı yakalandı ve toplam 1127,4 dakika sonra görüldü. En kötüsü gecelik işte çağrılan kaynakta 540 dakikaydı.
  • Bağlama 9 kaynak türünden 5’ini tanıdı; kalan 4 kaynak 45 satır istemci kodunu ve 124 milisaniye açılış işini yerinde tuttu.
  • Taşınabilirlik bedeli bağlamada 22 satır oldu (7 manifesto, 15 sahte kol); istemcide 0 kod satırı ve 19 yapılandırma değeri.

Sonraki Adım

Bu konu boyunca kenar sırayla kazandı: istek işleme, depolama, eşgüdümlü durum, eşzamansız iş ve bildirimsel erişim. Her kazanç bir kısıtla geldi. Geriye kısıtların toplamına bakmak kalıyor: kenar çalışma zamanının hiçbir dolambaçla aşamadığı sınırlar hangileri, bir işi kenara taşımanın anlamlı olduğu eşik nerede bitiyor. Bir sonraki ders bu sınırları toplar ve kursu kapatır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat