İçeriğe geç
academia.sh

Ders 04 / 21

Konteyner Standartları

Bir imaj biçimi belirtiminin taşıdığı söz üç parçaya ayrılır ve özet zincirini denetleyen bir doğrulayıcı yazılır; taşınabilirliğin nereye kadar gittiği sayılır: aynı belirtime uyan iki çalışma zamanı arasında ne değişmez, ne değişir.

İçindekiler

Önceki ders yalıtımı kuran üç mekanizmayı ölçtü ve üçünün de tek bir makinenin çekirdeğine ait olduğunu gösterdi. Ölçülen katman yığını ise bir makineye ait değildir: dizinlerden oluşan bir yığındır ve kopyalanıp taşınabilir. Taşınabilir olmak, taşındığı yerde aynı biçimde açılacağının güvencesi değildir. Katmanların hangi sırayla yığılacağı, hangi yapılandırmayla çalıştırılacağı ve bir katmanın yolda bozulmadığı bir yerde yazılı olmalıdır.

O yazının türü belirtimdir. Bu derste hiçbir belirtimin, gövdenin ya da ürünün adı geçmez; belirtimler ortak yapılarıyla anılır, çünkü ölçülen şey bir belgenin adı değil, o belgenin taşıdığı sözdür. KK20. Bir imaj biçimi belirtimi üç şey tanımlar: bir yapılandırma nesnesi, bir katman listesi ve içerik adresli bir özet zinciri. Bir çalışma zamanı belirtimi ise bu üçünü okuyup bir süreç başlatmanın kurallarını tanımlar.

Sözün üç parçası üç ayrı işe yarar. Yapılandırma nesnesi neyin çalıştırılacağını söyler: giriş noktası, çalışma dizini, kullanıcı, ortam değişkenleri. Katman listesi çıktının hangi parçalardan oluştuğunu ve her parçanın kaç bayt olduğunu söyler. Özet zinciri ise parçaların kimliğini ve sırasını birbirine bağlar; zincir sayesinde bir katmanın değişip değişmediği, değiştiyse yığının hangi noktasından itibaren başka bir çıktı olduğu hesaplanabilir.

İki belirtim türünün arasındaki sınır da burada çizilir. İmaj biçimi belirtimi durur hâldeki çıktıyı tanımlar: hangi baytlar, hangi sırayla, hangi kimlikle. Çalışma zamanı belirtimi ise koşan hâli tanımlar: bu tanımı okuyan bir çalışma zamanının hangi adımları hangi sırayla atacağını. Birinin bittiği yer diğerinin başladığı yerdir ve bu dersin ikinci bölümünde ölçülen farklar tam olarak o sınırın üstünde durur. Bir belirtimin adı bilinmeden de sözü okunabilir, çünkü söz her zaman aynı biçimdedir: neyi bağlıyor, neyi yoruma bırakıyor.

Kurgudaki bölgesel ölçüm ağının çıktısı bu üç parçayla tanımlanır. Aşağıdaki doğrulayıcı o tanımı denetler.

Zincirin Denetlenmesi

KK21. İmaj tanımı kurgudur; özetler node:crypto ile gerçekten hesaplanır ve ilk on iki onaltılık basamağa kısaltılır. KK22. Zincir kuralı tektir: z(0) = fark(0) ve z(n) = özet(z(n-1) + " " + fark(n)). KK23. Katmanların içerik boyutları önceki derslerin ölçtüğü değerlerdir.

// olcum-agi/dogrulayici.mjs — bir imaj biciminin ozet zincirini denetleyen dogrulayici
// Imaj tanimi KURGUDUR; ozetler node:crypto ile gercekten hesaplanir.
import { createHash } from "node:crypto";

const ozet = (v) => "s256:" + createHash("sha256").update(v).digest("hex").slice(0, 12);

// Katman icerikleri (kurgu): her katman bir bayt bloguyla temsil edilir.
const katmanIcerik = [
  ["taban-kok", Buffer.alloc(7_600_000, 48)],
  ["cozumleyici", Buffer.alloc(44_800_000, 49)],
  ["kural-paketi", Buffer.alloc(31_200_000, 50)],
  ["uygulama", Buffer.alloc(50_787, 51)],
];

// Belirtimin tasidigi soz uc parcadir: yapilandirma nesnesi, katman listesi,
// icerik adresli ozet zinciri. Zincir: z(0)=ozet(fark0), z(n)=ozet(z(n-1)+" "+fark(n)).
const zincirle = (farklar) =>
  farklar.reduce((z, f, i) => [...z, i === 0 ? f : ozet(z[i - 1] + " " + f)], []);

function imajTanimi(icerikler) {
  const katmanlar = icerikler.map(([ad, blok]) => ({ ad, boyut: blok.length, fark: ozet(blok) }));
  const zincir = zincirle(katmanlar.map((k) => k.fark));
  const yapilandirma = { girisNoktasi: "gecelik-is", calismaDizini: "/uygulama",
    kullanici: "olcum", zincir };
  return { yapilandirma, yapilandirmaOzeti: ozet(JSON.stringify(yapilandirma)), katmanlar };
}

// Dogrulayici: her katmanin ozeti yeniden hesaplanir, sonra zincir yeniden kurulur.
function dogrula(tanim, icerikler) {
  const bozuk = [];
  tanim.katmanlar.forEach((k, i) => { if (ozet(icerikler[i][1]) !== k.fark) bozuk.push(i); });
  const beklenen = zincirle(tanim.katmanlar.map((k) => k.fark));
  const zincirKirigi = beklenen.findIndex((z, i) => z !== tanim.yapilandirma.zincir[i]);
  return { bozuk, zincirKirigi, kirikSayisi: zincirKirigi < 0 ? 0 : beklenen.length - zincirKirigi };
}

const TANIM = imajTanimi(katmanIcerik);
console.log("katman listesi (icerik adresli)");
TANIM.katmanlar.forEach((k, i) => console.log("  " + String(i).padEnd(3) + k.ad.padEnd(14) +
  String(k.boyut).padStart(9) + " bayt  fark " + k.fark + "  zincir " + TANIM.yapilandirma.zincir[i]));
console.log("yapilandirma nesnesi ozeti: " + TANIM.yapilandirmaOzeti);
console.log("saglam tanim: " + JSON.stringify(dogrula(TANIM, katmanIcerik)));

// Tek bir bayt degistirilir: bagin nerede koptugu ve kac halkanin etkilendigi.
const bozukIcerik = katmanIcerik.map(([a, b], i) => i === 1
  ? [a, Buffer.concat([b.subarray(0, 5), Buffer.from("X"), b.subarray(6)])] : [a, b]);
const sonuc = dogrula(TANIM, bozukIcerik);
console.log("\n1 numarali katmanda 1 bayt degistirildi (44800000 baytin biri)");
console.log("  ozeti tutmayan katman: " +
  sonuc.bozuk.map((i) => `${i} (${TANIM.katmanlar[i].ad})`).join(", "));
console.log("  yeni fark: " + ozet(bozukIcerik[1][1]) + ", tanimdaki: " + TANIM.katmanlar[1].fark);

// Bozuk katman tanimla birlikte yeniden yayimlanirsa zincir nerede kirilir?
const yenidenTanim = imajTanimi(bozukIcerik);
const kirik = TANIM.yapilandirma.zincir
  .map((z, i) => z === yenidenTanim.yapilandirma.zincir[i]).indexOf(false);
console.log("  zincir " + kirik + ". halkada kirilir; " +
  (TANIM.yapilandirma.zincir.length - kirik) + "/" + TANIM.yapilandirma.zincir.length +
  " halka degisir, alttaki " + kirik + " halka aynen kalir");
console.log("  yapilandirma ozeti de degisir: " + yenidenTanim.yapilandirmaOzeti);
console.log("  yeniden tasinacak bayt: " +
  bozukIcerik.slice(kirik).reduce((t, [, b]) => t + b.length, 0) + "/" +
  katmanIcerik.reduce((t, [, b]) => t + b.length, 0));
katman listesi (icerik adresli)
  0  taban-kok       7600000 bayt  fark s256:1048de0c7a68  zincir s256:1048de0c7a68
  1  cozumleyici    44800000 bayt  fark s256:b0c7e6c28bfa  zincir s256:926ac9255c57
  2  kural-paketi   31200000 bayt  fark s256:99a2f404c480  zincir s256:08f1f6ea4359
  3  uygulama          50787 bayt  fark s256:3fbeb763e66c  zincir s256:ebdca65649c3
yapilandirma nesnesi ozeti: s256:06c1368bd196
saglam tanim: {"bozuk":[],"zincirKirigi":-1,"kirikSayisi":0}

1 numarali katmanda 1 bayt degistirildi (44800000 baytin biri)
  ozeti tutmayan katman: 1 (cozumleyici)
  yeni fark: s256:9b5c4ad8de20, tanimdaki: s256:b0c7e6c28bfa
  zincir 1. halkada kirilir; 3/4 halka degisir, alttaki 1 halka aynen kalir
  yapilandirma ozeti de degisir: s256:212730e2163b
  yeniden tasinacak bayt: 76050787/83650787

Doğrulayıcı sağlam tanımda hiçbir kusur bulmaz: bozuk katman listesi boş, zincir kırığı yok. Sonra 44.800.000 baytlık katmanın tek bir baytı değiştirilir ve o katmanın içerik özeti tutmaz. Bu, içerik adresliliğin tanımıdır — ad içeriğin kendisinden türetildiği için içerik değiştiğinde ad da değişir ve eşleşme tek bir karşılaştırmayla yakalanır. Yakalamanın hangi baytta olduğunu bilmek gerekmez ve aranan bayt sayısı da sonucu değiştirmez: 44,8 milyon baytta bir bayt ile yarısı değişmiş bir katman aynı biçimde, tek bir eşitsizlikle raporlanır. Bu, bir katmanı ada göre değil içeriğe göre adlandırmanın tek cümlelik karşılığıdır.

Zincirin katkısı bir adım ötededir. Bozuk katman tanımla birlikte yeniden yayımlanırsa zincir 1. halkada kırılır: dört halkanın üçü değişir, alttaki bir halka aynen kalır. Yani bir katmanın değişmesi kendisini ve üstündeki her şeyi yeni bir kimliğe taşır, altındakileri taşımaz. Bu asimetri taşınacak baytı belirler: 83.650.787 baytlık yığından 76.050.787 baytı yeniden taşınmalıdır, 7.600.000 baytlık taban olduğu yerde kalır. Zincirin sırayı da bağlaması bu yüzdendir — katmanların yeri değiştirilirse aynı farklar başka bir zincir üretir ve iki çıktı aynı sayılmaz.

Yapılandırma nesnesinin özeti de değişir, çünkü zincir onun içinde yazılıdır. Bu, üç parçanın tek bir kimliğe bağlandığı yerdir: bir çıktıyı tek bir özet adlandırır ve o özet hem neyin çalıştırılacağını hem hangi baytlardan oluştuğunu kapsar.

Doğrulamanın da bir bedeli vardır ve yalıtım bütçesinin bu derse düşen kalemi odur: tam doğrulama yığının tamamını okur — 83.650.787 bayt — ve dört içerik özeti ile üç zincir halkası hesaplar. Bedel çıktı büyüdükçe doğrusal artar ve her taşımada yeniden ödenir. Bunun karşılığında alınan şey tek bir baytın değişmediğinin kanıtlanabilir olmasıdır; bir katmanın yalnız adına bakan bir denetimde bu kanıt yoktur.

Zincirin bağlamadığı şey de yazılmalıdır. Özet, katmanın içeriğini bağlar, o içeriğin nasıl üretildiğini bağlamaz. Aynı katmanın iki kez üretilmesi aynı özeti verecek diye bir söz yoktur; zincir yalnız elindeki baytların değişmediğini söyler, o baytların yeniden üretilebilir olduğunu söylemez. Bu ayrım kurgudaki ağda somuttur: doğrulayıcı bozulmuş bir katmanı yakalar, ama iki ayrı makinede iki kez üretilen çözümleyici katmanı farklı özet verirse bunu bir bozulma olarak değil, iki ayrı çıktı olarak rapor eder. Doğrulayıcının söylediği ile söylemediği arasındaki sınır tam olarak buradadır ve sınırı bilmeden okunan bir “doğrulandı” satırı olduğundan fazlasını taahhüt eder.

Taşınabilirlik Nereye Kadar Gidiyor

Özet zinciri baytların taşındığını denetler. Taşınan baytların aynı biçimde davranacağını denetlemez. Belirtimin bağladığı şeyler ile yoruma bıraktığı şeyler ayrı ayrı sayılmalıdır.

KK24. On özellik iki kümeye ayrılır — belirtimin bağladığı beş, yoruma bıraktığı beş — ve ayrım modeldir. KK25. Taşınabilirlik oranı özellik sayısı üzerinden hesaplanır; ağırlıklandırma yapılmaz.

// olcum-agi/tasinabilirlik.mjs — ayni belirtime uyan iki calisma zamani karsilastirilir (model)
// Ozellikler iki kumeye ayrilir: belirtimin BAGLADIGI ve belirtimin YORUMA BIRAKTIGI.

const BAGLI = ["kok dosya sistemi duzeni", "katman sirasi ve birlesim kurali",
  "icerik ozeti algoritmasi", "giris noktasi ve calisma dizini", "ortam degiskeni kumesi"];
const YORUMA_BIRAKILAN = ["kaynak siniri yorumu", "gunluk cikisinin yazildigi yer",
  "varsayilan ag kipi", "kullanici eslemesi", "durdurma sinyali ve bekleme suresi"];

// Iki calisma zamani; bagli ozelliklerde ayni degeri tasimak zorundadir.
const CZ = {
  "calisma zamani 1": {
    "kok dosya sistemi duzeni": "katman yigini", "katman sirasi ve birlesim kurali": "alttan uste",
    "icerik ozeti algoritmasi": "s256", "giris noktasi ve calisma dizini": "gecelik-is @ /uygulama",
    "ortam degiskeni kumesi": "tanimda yazan 6 degisken",
    "kaynak siniri yorumu": "sinir asilinca surec durdurulur",
    "gunluk cikisinin yazildigi yer": "dosya", "varsayilan ag kipi": "kopru",
    "kullanici eslemesi": "birebir", "durdurma sinyali ve bekleme suresi": "nazik, 10 sn",
  },
  "calisma zamani 2": {
    "kok dosya sistemi duzeni": "katman yigini", "katman sirasi ve birlesim kurali": "alttan uste",
    "icerik ozeti algoritmasi": "s256", "giris noktasi ve calisma dizini": "gecelik-is @ /uygulama",
    "ortam degiskeni kumesi": "tanimda yazan 6 degisken",
    "kaynak siniri yorumu": "sinir asilinca istek reddedilir",
    "gunluk cikisinin yazildigi yer": "dosya", "varsayilan ag kipi": "ana makine agi",
    "kullanici eslemesi": "kaydirmali", "durdurma sinyali ve bekleme suresi": "nazik, 10 sn",
  },
};

const [A, B] = Object.keys(CZ);
const ayni = (o) => CZ[A][o] === CZ[B][o];
console.log("ozellik".padEnd(38) + "kume".padEnd(10) + "iki calisma zamaninda");
for (const o of [...BAGLI, ...YORUMA_BIRAKILAN])
  console.log(o.padEnd(38) + (BAGLI.includes(o) ? "bagli" : "yoruma").padEnd(10) +
    (ayni(o) ? "ayni" : `FARK  ${CZ[A][o]} / ${CZ[B][o]}`));

const degisen = YORUMA_BIRAKILAN.filter((o) => !ayni(o));
console.log(`\nbagli ozellik ${BAGLI.length}, yoruma birakilan ${YORUMA_BIRAKILAN.length}`);
console.log(`degismeden kalan ${BAGLI.length + (YORUMA_BIRAKILAN.length - degisen.length)}/10, ` +
  `degisen ${degisen.length}/10: ${degisen.join(", ")}`);
console.log(`tasinabilirlik: ciktinin kendisi %100 tasinir (ozet zinciri denetlenir), ` +
  `davranisin %${(BAGLI.length + YORUMA_BIRAKILAN.length - degisen.length) * 10}'u tasinir`);
console.log(`onceki derslerin sayimiyla: ortamdan 6 fark cikarildi, ` +
  `calisma zamani farki olarak ${degisen.length} yeni boyut geri geldi`);
ozellik                               kume      iki calisma zamaninda
kok dosya sistemi duzeni              bagli     ayni
katman sirasi ve birlesim kurali      bagli     ayni
icerik ozeti algoritmasi              bagli     ayni
giris noktasi ve calisma dizini       bagli     ayni
ortam degiskeni kumesi                bagli     ayni
kaynak siniri yorumu                  yoruma    FARK  sinir asilinca surec durdurulur / sinir asilinca istek reddedilir
gunluk cikisinin yazildigi yer        yoruma    ayni
varsayilan ag kipi                    yoruma    FARK  kopru / ana makine agi
kullanici eslemesi                    yoruma    FARK  birebir / kaydirmali
durdurma sinyali ve bekleme suresi    yoruma    ayni

bagli ozellik 5, yoruma birakilan 5
degismeden kalan 7/10, degisen 3/10: kaynak siniri yorumu, varsayilan ag kipi, kullanici eslemesi
tasinabilirlik: ciktinin kendisi %100 tasinir (ozet zinciri denetlenir), davranisin %70'u tasinir
onceki derslerin sayimiyla: ortamdan 6 fark cikarildi, calisma zamani farki olarak 3 yeni boyut geri geldi

Bağlı beş özellikte iki çalışma zamanı aynı değeri taşır ve taşımak zorundadır: kök dosya sistemi düzeni, katman sırası ile birleşim kuralı, içerik özeti algoritması, giriş noktası ile çalışma dizini, ortam değişkeni kümesi. Bunlar belirtimin sözüdür ve uyan her çalışma zamanında sabittir. Yoruma bırakılan beş özellikte ise bağlayıcılık yoktur; modelde beşinden üçü iki çalışma zamanında farklı çıkar.

Farkın hangi üçü olduğu önemlidir. Kaynak sınırı yorumu, önceki derste ölçülen kararın ta kendisidir: bir çalışma zamanında sınırı aşan süreç durdurulur, diğerinde istek reddedilir. Kurgudaki gecelik iş için bu, aynı çıktının bir yerde yarıda kesilmesi, başka bir yerde hatayı alıp sürmesi demektir. Ağ kipi ile kullanıcı eşlemesi de aynı türdendir — çıktı taşınır, davranış taşınmaz.

Aynı değeri taşıyan iki özellik de dikkatle okunmalıdır. Günlük çıkışının yazıldığı yer ile durdurma sinyali modelde iki çalışma zamanında da aynıdır; ama ikisi de yoruma bırakılan kümededir, yani aynı olmaları bir güvence değil, bir rastlantıdır. Bu ikisine dayanan bir varsayım — örneğin gecelik işin durdurulurken on saniye bekleyeceği — üçüncü bir çalışma zamanında sessizce bozulabilir ve bozulduğu yalnız koşumda görünür. İlk dersteki ayrım burada aynen yinelenir: bildirilmiş fark bir karar konusudur, bildirilmemiş fark bir sürprizdir. Yoruma bırakılan beş özelliğin hepsi, değerleri şu an aynı olsa bile, bildirilmemiş fark adaylarıdır.

Kapatmanın yolu da bu sayımdan çıkar. Yoruma bırakılan beş özellik, çalışma zamanının yapılandırmasında açıkça yazıldığı anda bağlı kümeye geçer: kaynak sınırı yorumu seçilir, ağ kipi belirtilir, kullanıcı eşlemesi bildirilir. Bu, belirtimi değiştirmez; belirtimin boş bıraktığı yeri çıktıyı çalıştıran tarafın doldurmasıdır. Bedeli de bellidir — beş satırlık bir bildirim ve o bildirimin her çalışma zamanı için ayrı ayrı doğrulanması. Bildirim yazılmadığı sürece taşınabilirlik %70’te kalır ve kalan %30 her taşımada yeniden ölçülmek zorundadır; yazıldığı anda ise ölçüm bir kez yapılır ve sonucu künyede durur.

Sayı da buradadır. Çıktının kendisi %100 taşınır, çünkü özet zinciri baytların aynı olduğunu denetler. Davranışın ise %70’i taşınır. Yalıtımın delindiği yer bu derste belirtimin kendisidir: özet zinciri baytları bağlar, davranışı bağlamaz ve bağlamadığı her özellik yeni bir fark boyutudur. İlk ders ortamdan 6 fark çıkarmıştı; çalışma zamanı farkı olarak 3 boyut geri gelir. Fark sıfırlanmaz, yeri değişir: ortam künyesinden çalışma zamanı yapılandırmasına taşınır. Kazancın ölçülebilir kalması da bu yüzden yeni bir künyeye bağlıdır — bu kez çalışma zamanının künyesine.

Özet

  • Bir imaj biçimi belirtimi üç şey tanımlar: yapılandırma nesnesi, katman listesi ve içerik adresli özet zinciri. Üçü tek bir kimliğe bağlanır.
  • Doğrulayıcı 44.800.000 baytlık bir katmandaki tek bayt değişikliğini içerik özetinden yakalar; içerik adresliliğin tanımı budur.
  • Zincir asimetriktir: bir katman değişince kendisi ve üstündekiler yeni kimlik alır, altındakiler almaz. Modelde 4 halkanın 3’ü değişir ve 83.650.787 baytın 76.050.787’si yeniden taşınır.
  • Aynı belirtime uyan iki çalışma zamanı bağlı beş özellikte aynıdır; yoruma bırakılan beş özellikten üçü farklıdır. Çıktı %100, davranış %70 taşınır.
  • Belirtim baytları bağlar, davranışı bağlamaz: ortamdan çıkarılan 6 farkın karşılığında çalışma zamanı farkı olarak 3 boyut geri gelir. Fark yok olmaz, künye değiştirir.

Sonraki Adım

Bu ders çıktının kimliğini ve taşınabilirliğinin sınırını yazdı; hepsi durur hâldeki çıktı üzerineydi. Çıktı bir kez çalıştırıldığında ise ölçülmemiş bir şey ortaya çıkar: koşan konteyner durur, ama arkasında ne bırakır? Önceki derste yazılabilir katmanın kopya-yukarı ile büyüdüğü görülmüştü; ağ adı, birim ve süreç kaydı da bir yerde tutulur. Sonraki ders yaşam döngüsünü bir durum makinesi olarak kurar, her geçişte tutulan kaynağı sayar ve durdurulmuş ama temizlenmemiş konteynerlerin bir dönem boyunca ne kadar biriktirdiğini ölçer.

İ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