İçeriğe geç
academia.sh

Ders 25 / 27

Yapılandırma Yönetimi Araçları

Ajanlı ve ajansız yapılandırma yönetimi tür olarak ölçülür: aynı otuz dört kalemlik ayar kümesi elli makineye iki modelde uygulanır; yayılma turu ve süresi, kısmi başarısızlıkta kayıttan ayrışan makine sayısı, sapmanın kaç dakika yaşadığı ve modelin kendi bedeli — ajan süreci, bağlantı yüzeyi, yetkili kimlik — sayılır.

İçindekiler

Önceki ders bir değişikliği uygulanmadan önce fiyatladı: plan kalemlerine birim maliyet bağlandı, tahminin ne kadar saptığı sayıldı, tahmin edilemeyen kalem adıyla yazıldı. Ama fiyatlanan şey kaynağın kendisiydi — kaç makine, hangi ölçüde, kaç disk. Kaynak oluşturulduktan sonra içine giren ayar o kaydın dışındadır: hangi paket sürümü kurulu, hangi dosya hangi izinle duruyor, hangi servis açılışta başlıyor. Bu ayarlar hâlâ elle giriliyor.

Sağlama kaynağı yaratır; yapılandırma yönetimi kaynağın içini kayda bağlar. İki model vardır ve ikisi de ürün olarak değil tür olarak anılır: ajanlı modelde makinede sürekli koşan bir süreç kaydı kendi çeker ve uygular; ajansız modelde merkezdeki bir koşucu makinelere bağlanıp ayarı iter. M22/K01 elle, betikle ve bildirimsel sağlamayı karşılaştırmıştı; o karşılaştırma burada tekrarlanmaz. Buradaki soru kaydı makineye taşıyan yolun kendisidir.

AD25. Filo, bölgesel ölçüm ağının — su sayaçlarından okuma toplayan kurgu yazılımın — okuma toplayıcılarını koşturan 50 makinedir. AD26. Kayıt 34 yapılandırma kalemi taşır; makinede değiştirilebilir ayar sayısı 61’dir. AD27. Bütün sayılar kendi üretecimizden gelir; tohumlar 20260731, 20260802 ve 20260803 görünürdür ve sayılar bir ölçüm değil, büyüklük mertebesidir. AD28. Ajansız koşucu aynı anda 12 makineye bağlanır, bağlantı 1 dakika, uygulama 4 dakika sürer; ajan 30 dakikada bir, kendi ofsetinde yoklar. AD29. Koşum anında makinelerin yüzde 8’i ağa kapalıdır, yüzde 4’ünde ajan süreci durmuştur; ajan kendi sürümünü günde bir kez dener, deneme yüzde 94 başarılıdır ve başarısızlığın yüzde 35’i ajanı öldürür. AD30. 30 günde makine başına 0,6 elle değişiklik düşer, ajansız model haftalık çizelgeye üç kayıt değişikliği koşumu ekler, ajan 46 MB bellek tutar ve bir kalem kayıtta 790 bayttır.

Aynı Ayar Kümesi, İki Yol

Aynı 34 kalem 50 makineye iki modelde uygulanır. Ajansız modelde eş zamanlı bağlantı sayısı tavan olduğu için filo turlara bölünür; ajanlı modelde tur yoktur, her ajan kendi ofsetinde bağımsız çeker.

// olcum-agi/model.mjs — ayni ayar kumesinin iki modelde yayilmasi (model; urun degil tur)
export const uretec = (tohum) => () =>
  (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;

export const KALEM = 34;    // kayittaki yapilandirma kalemi
export const PENCERE = 30;  // ajanli model: yoklama araligi (dk)
const KOL = 12, UYGULAMA = 4, BAGLANTI = 1;  // ajansiz: es zamanli kol, uygulama, baglanma (dk)

// Filo: yoklama ofseti, o anki ulasilabilirlik ve ajan durumu ureteçten gelir.
export const filo = (n, tohum = 20260731) =>
  Array.from({ length: n }, ((r) => () => ({
    ofset: Math.floor(r() * PENCERE), ulasilabilir: r() > 0.08, ajanCalisir: r() > 0.04,
  }))(uretec(tohum)));

const yuzde = (d, p) => d.slice().sort((a, b) => a - b)[Math.floor((p / 100) * d.length)];

// Ajansiz: merkez turlar halinde baglanir, ulasilamayan makine bu kosumda atlanir.
// Ajanli: her ajan kendi ofsetinde ceker; merkez sirasi yok, duran ajan disarida kalir.
export const kosum = (m, model) => {
  const ajansiz = model === "ajansiz";
  const hedef = m.filter((x) => (ajansiz ? x.ulasilabilir : x.ajanCalisir));
  const sure = ajansiz
    ? hedef.map((_, i) => (Math.floor(i / KOL) + 1) * (BAGLANTI + UYGULAMA))
    : hedef.map((x) => x.ofset + UYGULAMA);
  return {
    model, tur: ajansiz ? Math.ceil(hedef.length / KOL) : 1, ulasan: hedef.length,
    ayrisan: m.length - hedef.length, p50: yuzde(sure, 50), p95: yuzde(sure, 95),
    max: Math.max(...sure),
  };
};

if (import.meta.url === `file://${process.argv[1]}`) {
  const m = filo(50);
  console.log(`50 makine, kayitta ${KALEM} kalem, kayittaki toplam: ${50 * KALEM} satir\n`);
  console.log("model".padEnd(10) + "tur".padEnd(6) + "p50".padEnd(8) + "p95".padEnd(8) +
    "max".padEnd(8) + "ulasan".padEnd(9) + "ayrisan".padEnd(10) + "tutan satir");
  for (const s of ["ajansiz", "ajanli"].map((x) => kosum(m, x)))
    console.log(s.model.padEnd(10) + String(s.tur).padEnd(6) + `${s.p50} dk`.padEnd(8) +
      `${s.p95} dk`.padEnd(8) + `${s.max} dk`.padEnd(8) + `${s.ulasan}/50`.padEnd(9) +
      `${s.ayrisan}/50`.padEnd(10) + `${s.ulasan * KALEM}/${m.length * KALEM}`);
  console.log("\nfilo buyudugunde tam yayilma:");
  console.log("makine".padEnd(9) + "ajansiz tur".padEnd(13) + "ajansiz max".padEnd(13) +
    "ajanli tur".padEnd(12) + "ajanli max");
  for (const n of [50, 200, 800]) {
    const f = filo(n), a = kosum(f, "ajansiz"), b = kosum(f, "ajanli");
    console.log(String(n).padEnd(9) + String(a.tur).padEnd(13) + `${a.max} dk`.padEnd(13) +
      String(b.tur).padEnd(12) + `${b.max} dk`);
  }
}
50 makine, kayitta 34 kalem, kayittaki toplam: 1700 satir

model     tur   p50     p95     max     ulasan   ayrisan   tutan satir
ajansiz   4     10 dk   20 dk   20 dk   47/50    3/50      1598/1700
ajanli    1     21 dk   32 dk   33 dk   45/50    5/50      1530/1700

filo buyudugunde tam yayilma:
makine   ajansiz tur  ajansiz max  ajanli tur  ajanli max
50       4            20 dk        1           33 dk
200      16           80 dk        1           33 dk
800      63           315 dk       1           33 dk

Elli makinede ajansız model daha hızlıdır: dört turda, 20 dakikada biter; ajanlı model 33 dakika alır, çünkü en geç yoklayan ajan aralığın sonundadır. İkinci tablo bu sıralamayı bozar. Ajansız modelde tur sayısı filoyla doğru orantılı büyür — 800 makinede 63 tur, 315 dakika. Ajanlı modelde 33 dakika sabittir: paralellik merkezde değil makinelerdedir.

Son sütun bu kursun ölçüsüdür. Kayıt 1700 satır söyler; tek bir başarılı koşumdan sonra ajansız modelde 1598, ajanlı modelde 1530 satır gerçekten tutar. Fark kayıttan ayrışan makinelerden gelir: ağa kapalı 3 makine o koşumda atlanır, süreci durmuş 5 makine hiç bakmaz. Başarısızlık biçimi de aynı değildir. Ajansız modelde başarısızlık merkezden görülür — koşucu bağlanamadığını raporlar. Ajanlı modelde sessizdir: bakmayan ajan hata da üretmez; merkez, ajanın son ne zaman haber verdiğine bakmadıkça ayrışmayı fark etmez.

Sapma Ne Kadar Yaşıyor

Yayılma tek seferlik bir olaydır. Asıl fark, uygulamadan sonra makinede elle bir değişiklik yapıldığında ortaya çıkar. Ajanlı model sürekli bakar; ajansız model tetiklenir ve aradaki sürede sapma birikir. Bu kursun iac-temelleri konusu sürekli uzlaşma ile tetiklenen uygulama arasındaki farkı kurmuştu; burada o fark dakikayla sayılır.

// olcum-agi/sapma.mjs — iki modelde sapmanin kac dakika yasadigi (model)
import { uretec, filo, KALEM, PENCERE } from "./model.mjs";

const GUN = 1440, SON = 30 * GUN;
const AYAR = 61;    // makinede degistirilebilir ayar; bunun 34'u kayitta
const ORAN = 0.6;   // makine basina 30 gunde elle degisiklik (kurgu)
// Ajansiz model tetiklenir: haftalik cizelge + uc kayit degisikligi kosumu (kurgu gunler).
const TETIK = [0, 3.2, 7, 11.6, 14, 19.4, 21, 28].map((g) => Math.round(g * GUN));

const olaylar = (m, tohum = 20260802) => {
  const r = uretec(tohum);
  return m.flatMap((x) => (r() < ORAN
    ? [{ m: x, an: Math.floor(r() * SON), kayitta: r() * AYAR < KALEM }] : []))
    .sort((a, b) => a.an - b.an);
};

// Ajanli: her ajan kendi ofsetinde, PENCERE dakikada bir kayitla karsilastirir.
const ajanli = (o) => o.m.ajanCalisir
  ? ((((o.m.ofset - o.an) % PENCERE) + PENCERE) % PENCERE) || PENCERE : null;

// Ajansiz: bir sonraki tetige kadar yasar; makine o an kapaliysa bir tetik daha.
const ajansiz = (o) => {
  const k = TETIK.filter((t) => t > o.an);
  const t = o.m.ulasilabilir ? k[0] : k[1];
  return t === undefined ? null : t - o.an;
};

const say = (liste, omur) => {
  const g = liste.filter((o) => o.kayitta).map((o) => [o, omur(o)]);
  const kapali = g.filter(([, v]) => v !== null).map(([, v]) => v);
  // Acik kalan sapma pencerenin sonuna kadar yasar; toplama oyle girer.
  const acik = g.filter(([, v]) => v === null);
  const acikSure = acik.reduce((t, [o]) => t + (SON - o.an), 0);
  const kapaliSure = kapali.reduce((t, v) => t + v, 0);
  return [g.length, kapali.length, acik.length, Math.round(kapaliSure / kapali.length),
    Math.max(...kapali), kapali.filter((v) => v <= 60).length,
    kapaliSure + acikSure, acikSure / (kapaliSure + acikSure)];
};

const liste = olaylar(filo(50));
console.log(`30 gun, 50 makine, ${liste.length} elle degisiklik; ` +
  `kayit ${KALEM}/${AYAR} ayari kapsiyor\n`);
console.log("model".padEnd(10) + "tetik".padEnd(11) + "gorulen".padEnd(10) +
  "kapanan".padEnd(10) + "acik".padEnd(7) + "ort. omur".padEnd(12) + "en uzun".padEnd(11) +
  "1 saatte".padEnd(11) + "sapma-saati");
for (const [ad, tetik, fn] of [["ajanli", `${GUN / PENCERE}/gun`, ajanli],
  ["ajansiz", `${TETIK.length}/30 gun`, ajansiz]]) {
  const [olay, kap, ac, ort, uzun, saatte, top, pay] = say(liste, fn);
  console.log(ad.padEnd(10) + tetik.padEnd(11) + String(olay).padEnd(10) +
    String(kap).padEnd(10) + String(ac).padEnd(7) + `${ort} dk`.padEnd(12) +
    `${(uzun / 60).toFixed(1)} sa`.padEnd(11) + `${saatte}/${kap}`.padEnd(11) +
    (top / 60).toFixed(0) + ` (%${(100 * pay).toFixed(1)} acik kalandan)`);
}
console.log(`\nkayit disi ayarda olusan sapma: ${liste.filter((o) => !o.kayitta).length}` +
  ` olay - iki modelde de gorunmez`);
console.log(`kayit disi kalan ayar: ${AYAR - KALEM}/${AYAR} (makine basina)`);
30 gun, 50 makine, 27 elle degisiklik; kayit 34/61 ayari kapsiyor

model     tetik      gorulen   kapanan   acik   ort. omur   en uzun    1 saatte   sapma-saati
ajanli    48/gun     18        15        3      20 dk       0.5 sa     15/15      1251 (%99.6 acik kalandan)
ajansiz   8/30 gun   18        16        2      3873 dk     159.5 sa   0/16       1320 (%21.7 acik kalandan)

kayit disi ayarda olusan sapma: 9 olay - iki modelde de gorunmez
kayit disi kalan ayar: 27/61 (makine basina)

Olay başına iki mertebe fark vardır. Ajanlı modelde kapanan bir sapma ortalama 20 dakika yaşar ve on beşi de bir saat içinde kapanır. Ajansız modelde ortalama ömür 3873 dakikadır — iki buçuk günden fazla — ve on altısının hiçbiri bir saat içinde kapanmaz; en uzun sapma 159,5 saat, altı buçuk gün ayakta kalır. Fark, yoklama aralığı ile tetik aralığı arasındaki orandır.

Son sütun bu üstünlüğü geri alır. Otuz günlük toplam sapma süresi ajanlı modelde 1251, ajansız modelde 1320 saattir; fark yüzde altıdır. Nedeni tabloda yazılıdır: ajanlı modeldeki toplamın yüzde 99,6’sı hiç kapanmayan üç sapmadan gelir. Ajanı durmuş makinede sapma ölçüsüz yaşar, çünkü bakan yoktur; modelin hızı kendi başarısızlık biçimiyle yenilir. Ajansız modelde açık kalanın payı yüzde 21,7’dir — orada başarısızlık merkeze görünür ve sonraki tetikte düzelir.

Son iki satır iki modelin de kapsamadığı yeri yazar. Makinede 61 ayar değiştirilebilir, kayıt bunun 34’ünü tutar; otuz günde oluşan 27 değişikliğin 9’u kayıt dışı ayarlardadır ve iki modelde de görünmez. Sapmanın ne kadar hızlı kapandığı araç sorusudur; hangi sapmanın görüldüğü kaydın kapsamı sorusudur ve araç seçimi onu değiştirmez.

Modelin Kendi Bedeli

Her iki model de makineye bir şey ekler: ajanlı model bir süreç, ajansız model bir bağlantı noktası. Bedel ayrıca sayılır.

// olcum-agi/bedel.mjs — modelin kendi bedeli: surec, baglanti yuzeyi, kimlik (model)
import { uretec, filo, KALEM, PENCERE } from "./model.mjs";

const BELLEK = 46e6;   // ajan surecinin makinede tuttugu bellek (kurgu)
const BAYT = 790;      // bir yapilandirma kaleminin kayittaki bayti (kurgu)
const N = filo(50).length;
const cekme = (1440 / PENCERE) * N;        // ajanli: gunluk kayit cekme
const kosum = Math.round((8 / 30) * N);    // ajansiz: gunluk baglanti (30 gunde 8 kosum)
const mb = (b) => (b / 1e6).toFixed(1) + " MB";

const SATIR = [
  ["makinede kosan surec", `${N}`, "0"],
  ["makinede tutulan bellek", `${(N * BELLEK / 1e9).toFixed(2)} GB`, "0.00 GB"],
  ["makinede dinleyen uc", "0", `${N}`],
  ["merkezde dinleyen uc", "1", "0"],
  ["yetkili kimlik", `${N} (tek makineye acik)`, `1 (${N} makineye acik)`],
  ["bir kimlik dusunce", "1 makine", `${N} makine`],
  ["merkeze gunluk baglanti", `${cekme}`, `${kosum}`],
  ["merkezden gunluk trafik", mb(cekme * KALEM * BAYT), mb(kosum * KALEM * BAYT)],
];

// Ajanin kendi surumu de yayilmak zorundadir: gunde bir deneme, basarisizlik ajani oldurebilir.
const yayilim = (tohum = 20260803) => {
  const r = uretec(tohum), d = Array(N).fill("eski"), iz = [];
  for (let g = 1; g <= 14; g++) {
    for (let i = 0; i < N; i++)
      if (d[i] === "eski") d[i] = r() < 0.94 ? "yeni" : r() < 0.35 ? "olu" : "eski";
    if ([1, 3, 7, 14].includes(g))
      iz.push([g, ...["yeni", "eski", "olu"].map((v) => d.filter((x) => x === v).length)]);
  }
  return iz;
};

console.log("kalem".padEnd(28) + "ajanli".padEnd(24) + "ajansiz");
for (const [a, b, c] of SATIR) console.log(a.padEnd(28) + b.padEnd(24) + c);
console.log(`\najanin kendi surumu ${N} makineye yayilirken:`);
console.log("gun".padEnd(7) + "yeni surum".padEnd(13) + "eski surum".padEnd(13) + "olu ajan");
const iz = yayilim();
for (const [g, yeni, eski, olu] of iz)
  console.log(`${g}.`.padEnd(7) + `${yeni}/${N}`.padEnd(13) +
    `${eski}/${N}`.padEnd(13) + `${olu}/${N}`);
console.log(`\nolu ajanli ${iz.at(-1)[3]} makine kendini toparlayamaz: o makineye ancak ` +
  `ajansiz yoldan girilir; yilda 12 surumde ${iz.at(-1)[3] * 12} makineye el deger`);
kalem                       ajanli                  ajansiz
makinede kosan surec        50                      0
makinede tutulan bellek     2.30 GB                 0.00 GB
makinede dinleyen uc        0                       50
merkezde dinleyen uc        1                       0
yetkili kimlik              50 (tek makineye acik)  1 (50 makineye acik)
bir kimlik dusunce          1 makine                50 makine
merkeze gunluk baglanti     2400                    13
merkezden gunluk trafik     64.5 MB                 0.3 MB

ajanin kendi surumu 50 makineye yayilirken:
gun    yeni surum   eski surum   olu ajan
1.     46/50        3/50         1/50
3.     49/50        0/50         1/50
7.     49/50        0/50         1/50
14.    49/50        0/50         1/50

olu ajanli 1 makine kendini toparlayamaz: o makineye ancak ajansiz yoldan girilir; yilda 12 surumde 12 makineye el deger

İlk iki satır doğrudan bedeldir: ajanlı modelde filo, hiçbir ölçüm okuması yapmadan 2,30 GB bellek tutar. Üçüncü ve dördüncü satır yönü yazar: ajanlı modelde makinelerde dinleyen uç yoktur, ajan dışarı bağlanır ve merkezde tek bir uç dinler; ajansız modelde 50 makine uzaktan erişim için dinler, merkez hiç dinlemez.

Beşinci ve altıncı satır asıl ayrımdır. Ajanlı modelde her makinenin kendi kimliği vardır ve o kimlik yalnız kendi makinesini yazabilir; biri düşerse bir makine düşer. Ajansız modelde tek bir kimlik elli makinenin hepsinde yetkilidir; düşerse elli makine birden düşer. Kimlik sayısı ajanlı modelde elli kat fazladır, ama tek bir kimliğin bedeli elli kat azdır.

Son iki satır merkezin yükünü sayar: ajanlı modelde günde 2400 çekme ve 64,5 MB, ajansız modelde 13 bağlantı ve 0,3 MB. Aradaki 200 kat, sapmanın 20 dakikada kapanmasının fiyatıdır — sürekli bakmak sürekli sormak demektir.

Alt tablo ajanlı modelin kapanmayan halkasıdır. Ajanın kendisi de yazılımdır, yeni sürümü de yayılmak zorundadır. On dört günde 49 makine geçer, 1 makinede ajan ölür ve o makine kendini toparlayamaz: ajan çalışmadığı için yeni sürümü çekemez. Yılda on iki sürümde 12 makineye el değer ve ajanlı model, bir kaçış yolu olarak ajansız yolu da tutmayı gerektirir.

Özet

  • Elli makinede ajansız model 4 turda 20 dakikada, ajanlı model tek turda 33 dakikada yayılır; 800 makinede sıralama tersine döner — ajansız 63 tur ve 315 dakika, ajanlı hâlâ 33 dakika.
  • Tek koşumdan sonra kayıttaki 1700 satırın ajansız modelde 1598’i, ajanlı modelde 1530’u tutar; fark ağa kapalı 3 ile ajanı durmuş 5 makineden gelir ve ikincisi sessizdir.
  • Kapanan bir sapma ajanlı modelde ortalama 20 dakika, ajansız modelde 3873 dakika yaşar; en uzun ajansız sapma 6,6 gün ayakta kalır.
  • Toplam sapma süresi buna rağmen 1251 saate karşı 1320 saattir: ajanlı modeldeki toplamın yüzde 99,6’sı hiç kapanmayan üç sapmadan gelir.
  • Kaydın kapsamadığı 27/61 ayarda oluşan 9 sapma iki modelde de görünmez; kapanma hızı araç sorusu, hangi sapmanın görüldüğü kayıt sorusudur.
  • Modelin bedeli: ajanlı modelde 50 süreç, 2,30 GB bellek, günde 2400 çekme ve ölebilen bir ajan; ajansız modelde 50 dinleyen uç ve elli makinede birden yetkili tek kimlik.

Sonraki Adım

İki model de aynı varsayımı paylaşır: makine önce boş açılır, sonra yapılandırılır. Yayılma süresinin tamamı bu sıralamadan gelir — 20 dakika da 33 dakika da açılmış bir makineyi kayda getirmek için geçer. Kısmi başarısızlık da oradan gelir: makine kayda uymadan iş almaya başlamıştır.

Sıralama tersine çevrilebilir. Ayar açılıştan sonra taşınmak yerine makinenin açıldığı imajın içine önceden konabilir; makine kayda uygun doğarsa yayılma süresi sıfırdır. M22/K02 temel imajın boyutunu ve güncellenme yükünü ölçmüştü; o ölçüm tekrarlanmaz. Sonraki ders bir katman üstünü sayar: açılışta yapılandırma ile önceden pişmiş imaj yan yana konduğunda açılış kaç saniye sürüyor, dışarıya kaç çağrı gidiyor ve bir güvenlik düzeltmesi geldiğinde kaç imaj yeniden pişiyor?

İ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