İçeriğe geç
academia.sh

Ders 10 / 30

Yapılandırma ve Sır Nesneleri

Uygulama ayarlarının kümeden geçirilmesinin iki ölçüsü: aynı on dört anahtar ortam değişkeni ya da bağlanan dosya olarak geçirildiğinde değişikliğin kaç anahtar-tur gecikmeyle yansıdığı ve kaç tur kesinti ürettiği, ve bir sır nesnesini küme içinde kaç öznenin okuyabildiği.

İçindekiler

Önceki 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 kayıt deposuna bağlanacağı, hangi eşikle doğrulama yapacağı, hangi anahtarla fatura imzalayacağı. Bu değerler imajın içine yazılırsa üç ortam üç ayrı imaj demektir — ve o zaman imajın taşınabilirliği, yani M22/K02’de ölçülen özellik, ortadan kalkar. Dışarıda tutulursa kümeye bildirilen yeni bir nesne demektir.

Bu nesneler ikidir: açık değerleri taşıyan yapılandırma nesnesi ve gizli tutulması gereken değerleri taşıyan sır nesnesi. İkisi de aynı işi yapar; ayrımları taşıdıkları değerin görünürlüğüne dair bir beklentidir ve bu dersin ikinci yarısı o beklentinin ne kadar tuttuğunu sayar. M22/K01’in sızıntı yolu taraması burada tekrarlanmaz; oradaki soru bir değerin nerelere sızdığıydı, buradaki soru kümede kaç öznenin onu okumaya yetkili olduğudur. Ölçülen şey bir modeldir; değerler kurgudur.

TN25 — doğrulayıcı on dört ayar anahtarı okur, dördü gizli tutulmalıdır. TN26 — ortam değişkeni olarak geçirilen ayar süreç başlarken bir kez okunur; nesne değişse bile koşan süreç eski değeri görmeye devam eder. TN27 — dosya olarak bağlanan ayar üç tur sonra koşan kapsüle yansır ve süreç dosyayı yeniden okuduğu için yeniden başlatma gerekmez. TN28 — yeniden başlatma iki tur sürer ve o iki turda kapsül hizmet vermez. TN29 — bir nesneyi bağlayan kapsül, o kapsülün koştuğu düğümdeki aracı süreç ve denetim düzleminin iki bileşeni nesneyi okuyabilir; son ikisi yetki kuralıyla kapatılamaz. TN30 — yirmi dört turluk koşumda üç değişiklik olur: beşinci turda açık bir ayar, on ikinci turda gizli bir ayar, on dokuzuncu turda yine açık bir ayar.

Aynı Ayar, İki Biçim

Aşağıdaki koşum aynı on dört anahtarı ve aynı üç değişikliği dört düzende geçiriyor. Ölçülen büyüklük bayat anahtar-turdur: koşan kapsülün gördüğü değerin nesnedeki değerden farklı olduğu her anahtar, her tur için bir sayılır.

// ayar.mjs — ayni ayar kumesinin iki bicimde gecirilmesi (MODEL). Degerler kurgudur.
export const TUR = 24, YAYILIM = 3, YENIDEN = 2;          // TN27, TN28

export const ANAHTAR = [
  ['toplayici-adresi', false], ['dogrulama-esigi', false], ['gunluk-duzeyi', false],
  ['yeniden-deneme', false], ['zaman-asimi-tur', false], ['toplu-is-boyutu', false],
  ['bolge-kodu', false], ['olcum-birimi', false], ['rapor-araligi', false],
  ['onbellek-omru', false], ['kayit-deposu-parolasi', true], ['fatura-imza-anahtari', true],
  ['is-emri-belirteci', true], ['ariza-bildirim-anahtari', true],
];                                                        // TN25: 14 anahtar, 4'u gizli

// Degisiklik cizelgesi: hangi turda hangi anahtarin degeri degisiyor.
const DEGISIM = { 5: 'dogrulama-esigi', 12: 'fatura-imza-anahtari', 19: 'zaman-asimi-tur' };

// TN26: ortam degiskeni surec baslarken bir kez okunur; dosya bicimi YAYILIM tur sonra yansir.
export function kosum(bicim, yenidenBaslat) {
  const nesne = {}, gorunen = {};
  for (const [a] of ANAHTAR) { nesne[a] = 'kurgu-deger-0'; gorunen[a] = 'kurgu-deger-0'; }
  const bekleyen = [];
  let bayat = 0, yeniden = 0, kesinti = 0, kesintiSonu = -1;
  for (let t = 0; t < TUR; t++) {
    const ad = DEGISIM[t];
    if (ad) {
      nesne[ad] = `kurgu-deger-${t}`;
      const b = bicim(ad);
      if (b === 'dosya') bekleyen.push({ ad, an: t + YAYILIM });
      else if (yenidenBaslat) {                           // ortam bicimi: yalniz yeniden baslatmayla
        yeniden++; kesintiSonu = t + YENIDEN;
        for (const [x] of ANAHTAR) bekleyen.push({ ad: x, an: t + YENIDEN });
      }
    }
    for (let i = bekleyen.length - 1; i >= 0; i--) {      // yansiyan bildirim kuyruktan cikar
      if (bekleyen[i].an <= t) { gorunen[bekleyen[i].ad] = nesne[bekleyen[i].ad]; bekleyen.splice(i, 1); }
    }
    bayat += ANAHTAR.filter(([a]) => gorunen[a] !== nesne[a]).length;
    if (t <= kesintiSonu) kesinti++;
  }
  const kalan = ANAHTAR.filter(([a]) => gorunen[a] !== nesne[a]).length;
  return { bayat, yeniden, kesinti, kalan };
}

if (import.meta.url === `file://${process.argv[1]}`) {
  const s = (x, n) => String(x).padStart(n);
  const gizli = ANAHTAR.filter(([, g]) => g).length;
  console.log(`${ANAHTAR.length} anahtar (${gizli} gizli), ${TUR} tur, ${Object.keys(DEGISIM).length}`
    + ` degisiklik; yayilim ${YAYILIM} tur, yeniden baslatma ${YENIDEN} tur`);
  const BICIM = [
    ['hepsi ortam, yb yok', () => 'ortam', false, `${ANAHTAR.length}/0`],
    ['hepsi ortam, yb var', () => 'ortam', true, `${ANAHTAR.length}/0`],
    ['hepsi dosya', () => 'dosya', false, `0/${ANAHTAR.length}`],
    ['karma', (a) => (ANAHTAR.find(([x]) => x === a)[1] ? 'dosya' : 'ortam'), true,
      `${ANAHTAR.length - gizli}/${gizli}`],
  ];
  console.log(`${'bicim'.padEnd(22)}${s('ortam/dosya', 13)}${s('bayat anahtar-tur', 19)}`
    + `${s('yeniden baslatma', 18)}${s('kesinti turu', 14)}${s('sonda bayat', 13)}`);
  for (const [ad, f, yb, dagilim] of BICIM) {
    const r = kosum(f, yb);
    console.log(`${ad.padEnd(22)}${s(dagilim, 13)}${s(r.bayat, 19)}${s(r.yeniden, 18)}`
      + `${s(r.kesinti, 14)}${s(r.kalan, 13)}`);
  }
}
14 anahtar (4 gizli), 24 tur, 3 degisiklik; yayilim 3 tur, yeniden baslatma 2 tur
bicim                   ortam/dosya  bayat anahtar-tur  yeniden baslatma  kesinti turu  sonda bayat
hepsi ortam, yb yok            14/0                 36                 0             0            3
hepsi ortam, yb var            14/0                  6                 3             9            0
hepsi dosya                    0/14                  9                 0             0            0
karma                          10/4                  7                 2             6            0

Birinci satır ortam değişkeni biçiminin sessiz sonucudur. Hiçbir şey başarısız olmaz, hiçbir kesinti yaşanmaz — ve koşumun sonunda üç anahtar hâlâ yanlış değerdedir. Otuz altı bayat anahtar-tur, kimsenin fark etmediği bir sapmadır: nesne değişmiş, bildirim güncellenmiş, kapsül eski değerle çalışmaya devam etmiştir. Bildirimsel bir sistemde en tehlikeli durum budur, çünkü istenen durum ile gerçek durum arasındaki fark uzlaştırıcının baktığı yerde değildir; kopya sayısı doğrudur, kapsüller ayaktadır, yalnız içlerindeki değer eskimiştir.

İkinci satır bu sapmayı kapatıyor ve faturayı kesiyor. Değişiklikte yeniden başlatma yapılırsa bayat anahtar-tur otuz altıdan altıya iner, sonda bayat kalan sıfırdır — ama üç yeniden başlatma ve dokuz tur kesinti doğar. Yirmi dört turun dokuzu, yani neredeyse yüzde kırkı, tek satırlık bir ayar değişikliği yüzünden hizmet dışıdır. Bu bedelin kaynağı TN26’dır: ortam değişkeni sürece bir kez, başlangıçta verilir ve onu güncellemenin süreç ömrü içinde bir yolu yoktur.

Üçüncü satır iki ölçüyü de aynı anda düşürüyor: dokuz bayat anahtar-tur, sıfır yeniden başlatma, sıfır kesinti. Dosya olarak bağlanan ayar üç turluk bir yayılım gecikmesiyle koşan kapsüle ulaşır ve süreç dosyayı yeniden okuduğu için ayakta kalır. Üç değişiklik üç kez üçer tur bayatlık üretti; toplam dokuz. Bu, ikinci satırdaki altıdan üç fazladır — ama karşılığında dokuz turluk kesinti ortadan kalkmıştır.

Dördüncü satır yaygın bir bölüşümü ölçüyor: gizli dört anahtar dosya, açık on anahtar ortam değişkeni. Sonuç ikisinin ortasıdır — yedi bayat anahtar-tur, iki yeniden başlatma, altı tur kesinti — ve tam olarak üçüncü satırdan kötüdür. Karma düzen her iki biçimin de bedelini öder: açık ayarlar için kesinti, gizli ayarlar için yayılım gecikmesi. Bu bölüşümün gerekçesi yansıma hızı değil, bir sonraki bölümde ölçülen görünürlüktür; ama tabloya bakan biri karma düzenin kendiliğinden daha iyi olduğunu söyleyemez.

Dört satırın ortak dersi, sapmanın nerede ölçüldüğüyle ilgilidir. Kopya kümesi denetleyicisi istenen sayı ile gerçek sayıyı karşılaştırır ve farkı kapatır; ayar değerleri o karşılaştırmanın dışındadır. Nesnedeki değer ile koşan süreçteki değer arasındaki fark hiçbir denetleyicinin baktığı yerde değildir, bu yüzden birinci satırda yirmi dört tur boyunca kimse bir şey fark etmez. Bildirimsel bir sistemde uzlaştırılmayan her alan, sessizce sapabilen bir alandır.

Sır Nesnesinin Görünürlüğü

Gizli anahtarları ayrı bir nesne türünde tutmanın gerekçesi görünürlüktür. Bu bölüm o gerekçeyi sayıya çeviriyor: aynı yetki şemasıyla, aynı kümede, bir sır nesnesini kaç özne okuyabiliyor.

// gorunurluk.mjs — bir sir nesnesini kume icinde kac ozne okuyabiliyor (MODEL).
import { ANAHTAR } from './ayar.mjs';

// Kendi kucuk yetki semamiz: bir kural bir ozneye, bir nesne turu ve ad kalibi uzerinde fiil verir.
export const YETKI_SEMA = { ozne: 'metin', tur: 'metin|*', ad: 'metin|*', fiil: 'liste' };

const KAPSULLER = {                                       // hangi kapsul hangi dugumde kosuyor
  'dogrulayici-kapsulu': 'dugum-1', 'faturalama-kapsulu': 'dugum-2',
  'toplayici-kapsulu': 'dugum-3',
};
const BAGLAYAN = {                                        // hangi nesneyi hangi kapsuller bagliyor
  'fatura-imza-anahtari': ['dogrulayici-kapsulu', 'faturalama-kapsulu'],
  'dogrulama-esigi': ['dogrulayici-kapsulu', 'faturalama-kapsulu', 'toplayici-kapsulu'],
};
const DENETIM_DUZLEMI = ['durum-deposu', 'kume-arayuzu'];  // her iki nesneyi de tasir

const ROLLER = {
  genis: [
    { ozne: 'islet-rolu', tur: '*', ad: '*', fiil: ['oku', 'yaz'] },
    { ozne: 'gozlem-rolu', tur: '*', ad: '*', fiil: ['oku'] },
    { ozne: 'yayin-oznesi', tur: '*', ad: '*', fiil: ['oku', 'yaz'] },
    { ozne: 'yedekleme-oznesi', tur: '*', ad: '*', fiil: ['oku'] },
    { ozne: 'denetim-oznesi', tur: '*', ad: '*', fiil: ['oku'] },
  ],
  'en az': [
    { ozne: 'islet-rolu', tur: 'yapilandirma', ad: '*', fiil: ['oku', 'yaz'] },
    { ozne: 'gozlem-rolu', tur: 'yapilandirma', ad: '*', fiil: ['oku'] },
    { ozne: 'yayin-oznesi', tur: 'sir', ad: 'fatura-imza-anahtari', fiil: ['yaz'] },
    { ozne: 'yedekleme-oznesi', tur: 'yapilandirma', ad: '*', fiil: ['oku'] },
    { ozne: 'denetim-oznesi', tur: 'yapilandirma', ad: '*', fiil: ['oku'] },
  ],
};

export function okuyabilen(nesne, tur, politika) {
  const kapsul = BAGLAYAN[nesne] ?? [];
  const araci = [...new Set(kapsul.map((k) => `araci-${KAPSULLER[k]}`))];
  const rol = ROLLER[politika]
    .filter((r) => (r.tur === '*' || r.tur === tur) && (r.ad === '*' || r.ad === nesne)
      && r.fiil.includes('oku'))
    .map((r) => r.ozne);
  return { kapsul, rol, araci, duzlem: DENETIM_DUZLEMI };
}

if (import.meta.url === `file://${process.argv[1]}`) {
  const s = (x, n) => String(x).padStart(n);
  const gizli = ANAHTAR.filter(([, g]) => g).length;
  console.log(`${ANAHTAR.length} anahtarin ${gizli} tanesi sir nesnesinde, ${ANAHTAR.length - gizli}`
    + ` tanesi yapilandirma nesnesinde; yetki semasi: ${Object.keys(YETKI_SEMA).join(', ')}`);
  console.log(`${'nesne'.padEnd(24)}${'tur'.padEnd(14)}${'politika'.padEnd(9)}${s('kapsul', 8)}`
    + `${s('rol', 5)}${s('araci surec', 13)}${s('denetim duzlemi', 17)}${s('toplam', 8)}`);
  for (const [nesne, tur] of [['fatura-imza-anahtari', 'sir'], ['dogrulama-esigi', 'yapilandirma']]) {
    for (const p of ['genis', 'en az']) {
      const r = okuyabilen(nesne, tur, p);
      const toplam = r.kapsul.length + r.rol.length + r.araci.length + r.duzlem.length;
      console.log(`${nesne.padEnd(24)}${tur.padEnd(14)}${p.padEnd(9)}${s(r.kapsul.length, 8)}`
        + `${s(r.rol.length, 5)}${s(r.araci.length, 13)}${s(r.duzlem.length, 17)}${s(toplam, 8)}`);
    }
  }
  const az = okuyabilen('fatura-imza-anahtari', 'sir', 'en az');
  console.log(`\nen az yetkide sir nesnesini okuyabilenler: ${[...az.kapsul, ...az.rol,
    ...az.araci, ...az.duzlem].join(', ')}`);
  console.log(`bunlarin ${az.araci.length + az.duzlem.length} tanesi yetki kuraliyla kaldirilamaz`);
}
14 anahtarin 4 tanesi sir nesnesinde, 10 tanesi yapilandirma nesnesinde; yetki semasi: ozne, tur, ad, fiil
nesne                   tur           politika   kapsul  rol  araci surec  denetim duzlemi  toplam
fatura-imza-anahtari    sir           genis           2    5            2                2      11
fatura-imza-anahtari    sir           en az           2    0            2                2       6
dogrulama-esigi         yapilandirma  genis           3    5            3                2      13
dogrulama-esigi         yapilandirma  en az           3    4            3                2      12

en az yetkide sir nesnesini okuyabilenler: dogrulayici-kapsulu, faturalama-kapsulu, araci-dugum-1, araci-dugum-2, durum-deposu, kume-arayuzu
bunlarin 4 tanesi yetki kuraliyla kaldirilamaz

İlk ve üçüncü satırlar birlikte okunmalıdır. Geniş yetki politikasında sır nesnesini on bir, açık yapılandırma nesnesini on üç özne okuyabiliyor. Aradaki iki fark, sırrı bağlayan kapsülün bir eksik olmasından geliyor — rol sayısı ikisinde de beştir. Nesnenin türü sır olduğu için hiçbir rol daralmadı. Bu, bu bölümün ilk sonucudur: bir değeri sır nesnesine koymak, onu kimin okuyabildiğini tek başına değiştirmez; değiştiren şey yetki kuralıdır ve o kural ayrıca yazılmalıdır.

İkinci satır kuralı yazınca ne olduğunu gösteriyor. En az yetkili politikada sır nesnesini okuyan rol sayısı beşten sıfıra iner; toplam on birden altıya düşer. Aynı politikada yapılandırma nesnesi on ikide kalır, çünkü açık ayarları okumak dört rolün işidir. İki nesne türü arasındaki asıl fark burada doğar — türde değil, o türe yazılan kuralda.

Son iki satır ise daralmanın nerede durduğunu söylüyor. En az yetkide bile altı okuyucu vardır ve dördü yetki kuralıyla kaldırılamaz: sırrı bağlayan kapsüllerin koştuğu iki düğümdeki aracı süreçler ile denetim düzleminin iki bileşeni. Aracı süreç, kapsülün dosya alanını kurduğu için değeri görmek zorundadır; durum deposu ile küme arayüzü nesneyi sakladıkları ve dağıttıkları için görürler. Bir sır nesnesi kümeye yazıldığı anda bu dört okuyucu doğar ve hiçbir rol tanımı onları azaltmaz. Sayı sıfıra inmez, dörde iner.

Devredilen Karar ve Bilmediği Şey

Devredilen karar burada ayarın kapsüle nasıl ulaşacağıdır. Daha önce bu karar imajı üreten kişideydi: değer imajın içine yazılırdı ve her ortam için ayrı imaj üretilirdi. Karar kümeye geçtiğinde sistemin bilmesi gereken üç bilgi kalemi doğar: hangi anahtarın hangi biçimde geçeceği, değişikliğin ne kadar sürede yansıması gerektiği, ve hangi anahtarın gizli sayılacağı. Üçü de bildirimdir, ölçüm gerektirmez; maliyetleri yazılmalarında değil, yanlış yazıldıklarında hiçbir şeyin uyarmamasındadır.

Sistemin bilmediği şey, sürecin ayarı ne zaman okuduğudur. Model bunu TN26 ve TN27 ile varsayım hâline getirdi; gerçekte bunu bilen tek yer sürecin kendi kodudur ve küme oraya bakamaz. Bu bilgisizliğin bedeli birinci tablonun ilk satırında duruyor: otuz altı bayat anahtar-tur ve sonda üç yanlış değer, hiçbir hata kaydı üretmeden. Yeniden başlatma kararı da aynı bilgisizlikten doğar — süreç dosyayı yeniden okusa gerekmeyecek olan dokuz turluk kesinti, okuyup okumadığı bilinmediği için ödenir.

İkinci tabloda ise devretmenin kazandırmadığı bir alan görünüyor. Gizli değeri ayrı bir nesne türüne taşımak, görünürlüğü on üçten on bire indirdi; asıl indirimi yapan yetki kuralı oldu ve o kural insan tarafından yazıldı. Sistem hangi rolün hangi sırra gerçekten ihtiyacı olduğunu bilmez; bunu bilebilmesi için her öznenin her nesneye erişimini gözlemesi ve kullanılmayanı düşürmesi gerekirdi. Bilinmediği için varsayılan geniş kalır ve beş rol, ihtiyacı olmadığı hâlde okuma yetkisini taşır.

Özet

  • Aynı on dört anahtar dört düzende geçirildi. Ortam değişkeni biçiminde yeniden başlatma yapılmazsa otuz altı bayat anahtar-tur doğar ve koşumun sonunda üç anahtar hâlâ yanlış değerdedir; hiçbir hata kaydı üretilmez.
  • Değişiklikte yeniden başlatmak bayat anahtar-turu altıya indirir ama üç yeniden başlatma ve yirmi dört turun dokuzunda kesinti üretir.
  • Dosya olarak bağlama dokuz bayat anahtar-tur, sıfır yeniden başlatma ve sıfır kesinti verir; yayılım gecikmesi değişiklik başına üç turdur.
  • Gizliyi dosya, açığı ortam değişkeni yapan karma düzen yedi bayat anahtar-tur ile altı tur kesinti üretir — her iki biçimin de bedelini öder ve yalnız dosya biçiminden kötüdür.
  • Bir değeri sır nesnesine koymak görünürlüğü tek başına daraltmaz: geniş politikada beş rol her iki nesne türünü de okuyabiliyor; daraltan şey ayrıca yazılan yetki kuralıdır.
  • En az yetkili politikada sır nesnesinin okuyucusu on birden altıya iner, ama sıfıra inmez: iki düğümdeki aracı süreç ile denetim düzleminin iki bileşeni yetki kuralıyla kaldırılamaz.

Sonraki Adım

Yapılandırma ve sır nesneleri kapsüle bir dosya alanı üzerinden ulaştı ve o alan kapsülle birlikte doğup kapsülle birlikte öldü. Bu, ayarlar için doğru davranıştır: değer nesnede durur, kapsül gittiğinde bir şey kaybolmaz. Uygulamanın ürettiği veri için ise aynı davranış bir veri kaybı demektir. Kayıt deposu kapsülü yeniden başladığında sayaç okumaları da onunla gitmemelidir; oysa bu konuda ölçülen her şey — kopya kümesinin sildiği kapsüller, geçişte kurulan yeni sürüm, devirle gelip giden uç noktalar — kapsülün ömrünün kısa olduğunu varsaydı. Sonraki ders bu varsayımın kırıldığı yeri ele alır: kapsülden uzun yaşayan bir veri alanının kümeye nasıl bildirildiği ve o bildirimin taşıdığı yeni bilgi kalemleri.

İ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