Ders 20 / 30
Dikey ve Küme Ölçekleme
Kaynak boyutlandırma ve düğüm eklemenin ölçülmesi: dikey boyutlandırmanın bedeli olan yeniden başlatma sayısı ile kazancı olan boş kapasite düşüşünün karşılaştırılması, yeni düğümün hazır olma gecikmesi taranarak kaç tur kapasitesiz kalındığının sayılması ve üç ölçekleme türünün birbirini bozduğu durumun bir örnekle gösterilmesi.
İçindekiler
Önceki dersin denetleyicisi tek bir kolu çeviriyordu: kopya sayısı. İki kol daha var. Kopyanın kendisi büyütülüp küçültülebilir — kapsülün isteği gözlenen kullanıma göre yeniden yazılabilir. Küme büyütülüp küçültülebilir — düğüm eklenip çıkarılabilir. Üçü de aynı yükü karşılar ve üçünün bilgi maliyeti farklıdır.
Bu iki kolun ortak yanı, karşılığın anında alınamamasıdır. Kopya sayısını değiştirmek bir sayaç işlemidir; kapsülün isteğini değiştirmek onu yeniden başlatmayı gerektirir, düğüm eklemek ise düğümün hazır olmasını bekletir. Bu ders iki gecikmeyi ayrı ayrı sayar ve sonunda üç kolun aynı anda çevrildiğinde ne olduğunu gösterir. Ölçülen şey bir modeldir; iş yükü bölgesel ölçüm ağının (kurgu) servisleridir ve kaç kopya gerektiğinin aritmetiği kapasite planlamasından gelen girdidir.
Dikey Boyutlandırma: Bedel Yeniden Başlatma
Modelde altı kapsül 120 tur boyunca izlenir. Başlangıç isteği 1.024 birimdir, yani gerçek kullanımın epey üstünde bildirilmiştir. Bir öneri üretici son on turun tepesini alır ve bildirilen istekten belirli bir eşikten fazla saparsa isteği yeniden yazar; her yazma kapsülü yeniden başlatır ve iki tur hizmet dışı bırakır.
// zamanlama/dikey.mjs — dikey boyutlandirma: bedel yeniden baslatma, kazanc bos kapasitenin // dusmesi. Kurulan sey bir MODELDIR; gercek kume kosturulmaz. export const TUR = 120, KAPSUL = 6; export const PENCERE = 10; // ZO31: oneri son 10 turun tepesinden cikar export const KESINTI = 2; // ZO32: her yeniden boyutlandirma kapsulu 2 tur hizmet disi birakir const TOHUM = 20260806; export function uretec(tohum = TOHUM) { let s = tohum % 2147483647; return () => (s = (s * 48271) % 2147483647) / 2147483647; } // ZO33: kullanim 480 birim cevresinde dalgalanir, iki kapsul yavasca suruklenir, ±%12 gurultu. export function kullanimSerileri() { const r = uretec(); return Array.from({ length: KAPSUL }, (_, k) => Array.from({ length: TUR }, (_, t) => { const taban = 480 + 100 * Math.sin((2 * Math.PI * t) / 30) + (k % 3 === 0 ? 1.6 * t : 0); return Math.max(80, Math.round(taban * (0.88 + 0.24 * r()))); })); } export const SERILER = kullanimSerileri(); // Oneri: son PENCERE turun tepesi. Sapma esigi asilirsa istek degisir ve kapsul yeniden baslar. export function boyutlandir(esik) { let baslatma = 0, israf = 0, yetersiz = 0, kesintiTur = 0, istekTur = 0; for (const seri of SERILER) { let istek = 1024, kalan = 0; // ZO34: ilk istek 1024 birim (siserek bildirilmis) for (let t = 0; t < TUR; t++) { const oneri = Math.max(...seri.slice(Math.max(0, t - PENCERE + 1), t + 1)); if (esik >= 0 && Math.abs(oneri - istek) / istek > esik && kalan === 0) { istek = oneri; baslatma++; kalan = KESINTI; } if (kalan > 0) { kalan--; kesintiTur++; } istekTur += istek; israf += Math.max(0, istek - seri[t]); if (seri[t] > istek) yetersiz++; } } return { baslatma, israf, yetersiz, kesintiTur, istekTur }; } if (process.argv[1].endsWith("dikey.mjs")) { const kullanimTur = SERILER.flat().reduce((a, b) => a + b, 0); console.log(`model: ${KAPSUL} kapsul x ${TUR} tur (tohum ${TOHUM}); gercek kullanim toplami ` + `${kullanimTur} birim-tur, ilk istek 1024 birim`); const s = (x, n = 16) => String(x).padStart(n); console.log(`\n${"esik".padEnd(14)}${s("yeniden baslatma")}${s("hizmet disi tur")}` + `${s("bos istek")}${s("bos oran")}${s("yetersiz tur")}`); for (const [ad, esik] of [["sabit istek", -1], ["%5", 0.05], ["%10", 0.10], ["%20", 0.20], ["%35", 0.35], ["%50", 0.50]]) { const o = boyutlandir(esik); console.log(`${ad.padEnd(14)}${s(o.baslatma)}${s(o.kesintiTur)}${s(o.israf)}` + `${s("%" + ((o.israf / o.istekTur) * 100).toFixed(1))}${s(o.yetersiz)}`); } const a = boyutlandir(-1), b = boyutlandir(0.20); console.log(`\nsabit istekten %20 esigine: bos istek ${a.israf} -> ${b.israf} birim-tur ` + `(%${(100 * (1 - b.israf / a.israf)).toFixed(1)} dusus), bedeli ${b.baslatma} yeniden baslatma ` + `ve ${b.kesintiTur} hizmet disi tur`); }
model: 6 kapsul x 120 tur (tohum 20260806); gercek kullanim toplami 367748 birim-tur, ilk istek 1024 birim esik yeniden baslatma hizmet disi tur bos istek bos oran yetersiz tur sabit istek 0 0 369532 %50.1 0 %5 141 280 57939 %13.7 75 %10 87 174 56176 %13.3 113 %20 38 76 54704 %13.2 190 %35 10 20 64938 %15.4 180 %50 8 16 51564 %13.2 336 sabit istekten %20 esigine: bos istek 369532 -> 54704 birim-tur (%85.2 dusus), bedeli 38 yeniden baslatma ve 76 hizmet disi tur
Üç Sütun Aynı Anda İyileşmiyor
Sabit istek satırı başlangıç noktasıdır: hiç yeniden başlatma yok, hiç yetersiz tur yok, ve isteğin yüzde 50,1’i boşta duruyor. Bildirim iki katına şişirildiğinde ödenen bedel budur — birinci dersin israfı, burada bir zaman serisi olarak görünüyor.
Eşik yüzde 20’ye kurulduğunda boş oran yüzde 13,2’ye iniyor: 369.532 birim-turluk boş istek 54.704’e düşüyor, yani yüzde 85,2 kazanç. Bedeli 38 yeniden başlatma ve 76 hizmet dışı turdur. Eşik yüzde 5’e indirildiğinde boş oran yalnız yüzde 13,7’de kalırken yeniden başlatma sayısı 141’e, hizmet dışı tur 280’e çıkıyor. Daha sıkı takip daha çok kazanç getirmiyor, yalnız daha çok kesinti getiriyor.
Üçüncü sütun karşılıksız değil. Sabit istekte yetersiz tur sıfırken, yüzde 20 eşiğinde 190, yüzde 50’de 336 tur yetersiz kalıyor: istek gerçek kullanıma yaklaştıkça tepe anlarında sınır aşılıyor. Dikey boyutlandırma boş kapasiteyi yetersizliğe çeviriyor ve aradaki dengeyi belirleyen tek şey eşiktir. Eşiğin kendisi de bir tahmindir — yüzde 35 satırı yüzde 20’den daha çok israf üretiyor, çünkü öneri bir tepe değerine takılıp orada kalıyor. Sıralamanın tek yönlü olmaması, ayarın ölçülmeden seçilemeyeceğini gösterir.
Küme Ölçeklemesi: Bedel Hazır Olma Gecikmesi
İkinci kol düğüm sayısıdır. Yük 800 istek/s’den 12.000 istek/s’ye tırmanır; ölçekleme denetleyicisi kopya ekler, kopyalar düğüme sığmadığında küme ölçekleyici düğüm sipariş eder ve yeni düğüm belirli tur sonra hazır olur. Ölçüt gecikmesi bu modelde sıfırdır, böylece ölçülen tek gecikme düğümün hazır olma süresidir.
// zamanlama/kume.mjs — kume olceklemesi: yeni dugumun hazir olma gecikmesi yuke yetisiyor mu, // ve uc olcekleme turunun birbirini bozdugu durum. Model; gercek kume kosturulmaz. import { TUR, uretec } from "./dikey.mjs"; const DOYUM = 1176.47, HEDEF = 0.70; // M19'un girdileri; aritmetik burada tekrarlanmaz const KOPYA_BASINA = 4; // ZO35: bir dugume dort kopya sigar const KUCULTME_PENCERESI = 5; // Yuk 800'den 12000 istek/s'ye tirmaniyor, uzerine dalga ve ±%6 gurultu (kurgu). const r = uretec(20260807); const YUK = Array.from({ length: TUR }, (_, t) => Math.round((800 + 95 * t + 600 * Math.sin((2 * Math.PI * t) / 25)) * (0.94 + 0.12 * r()))); const gereken = (y) => Math.max(1, Math.ceil(y / (DOYUM * HEDEF))); // ZO36: dikey boyutlandirma her 10. turda bir kopyayi 2 tur hizmet disi birakir. function kostur({ hazir, dugumSiniri = 99, dikey = false }) { let kopya = 1, hazirDugum = 1, bekleyen = [], bosSayac = 0; let kapasitesizTur = 0, enUzun = 0, seri = 0, dugumTur = 0, kopyaTur = 0; let olay = 0, siparis = 0, baslatma = 0; for (let t = 0; t < TUR; t++) { bekleyen = bekleyen.filter((v) => { if (v <= t) { hazirDugum++; return false; } return true; }); const kisitli = Math.min(hazirDugum, dugumSiniri) * KOPYA_BASINA; const yenidenBaslayan = dikey && t % 10 < 2 ? 1 : 0; if (dikey && t % 10 === 0) baslatma++; const hizmetVeren = Math.max(1, Math.min(kopya, kisitli) - yenidenBaslayan); const doluluk = YUK[t] / (hizmetVeren * DOYUM); const istenen = Math.max(1, Math.ceil((kopya * doluluk) / HEDEF)); if (istenen !== kopya) olay++; kopya = istenen; if (kopya > kisitli) { const ek = Math.ceil((kopya - kisitli) / KOPYA_BASINA); for (let i = 0; i < ek; i++) bekleyen.push(t + hazir); siparis += ek; } else if (kisitli - kopya >= KOPYA_BASINA && hazirDugum > 1) { if (++bosSayac >= KUCULTME_PENCERESI) { hazirDugum--; bosSayac = 0; } } else bosSayac = 0; const calisan = Math.min(kopya, Math.min(hazirDugum, dugumSiniri) * KOPYA_BASINA); kopyaTur += calisan; dugumTur += hazirDugum + bekleyen.length; if (calisan < gereken(YUK[t])) { kapasitesizTur++; enUzun = Math.max(enUzun, ++seri); } else seri = 0; } return { kapasitesizTur, enUzun, dugumTur, kopyaTur, olay, siparis, baslatma }; } const s = (x, n = 16) => String(x).padStart(n); console.log(`yuk ${Math.min(...YUK)}–${Math.max(...YUK)} istek/s, ${TUR} tur; gereken kopya ` + `${gereken(YUK[0])}–${Math.max(...YUK.map(gereken))}, dugum basina ${KOPYA_BASINA} kopya`); console.log(`\nyeni dugumun hazir olma gecikmesi taraniyor:`); console.log(`${"gecikme".padEnd(10)}${s("kapasitesiz tur")}${s("en uzun seri")}${s("dugum siparisi")}` + `${s("dugum-tur")}${s("kopya-tur")}`); for (const hazir of [0, 1, 2, 4, 6, 8]) { const o = kostur({ hazir }); console.log(`${String(hazir).padEnd(10)}${s(o.kapasitesizTur)}${s(o.enUzun)}${s(o.siparis)}` + `${s(o.dugumTur)}${s(o.kopyaTur)}`); } console.log(`\nuc olcekleme turu bir arada (hazir olma gecikmesi 4):`); console.log(`${"ayar".padEnd(30)}${s("olcekleme olayi", 18)}${s("kapasitesiz tur", 18)}` + `${s("yeniden baslatma", 18)}${s("dugum-tur", 18)}`); for (const [ad, ek] of [["yalniz yatay (dugum bol)", { hazir: 0, dugumSiniri: 99 }], ["yatay + kume", { hazir: 4 }], ["yatay + kume + dikey", { hazir: 4, dikey: true }]]) { const o = kostur(ek); console.log(`${ad.padEnd(30)}${s(o.olay, 18)}${s(o.kapasitesizTur, 18)}` + `${s(o.baslatma, 18)}${s(o.dugumTur, 18)}`); } const b = kostur({ hazir: 4 }), c = kostur({ hazir: 4, dikey: true }); console.log(`\ndikey eklenince: olcekleme olayi ${b.olay} -> ${c.olay}, dugum siparisi ` + `${b.siparis} -> ${c.siparis}, dugum-tur ${b.dugumTur} -> ${c.dugumTur}`);
yuk 792–12189 istek/s, 120 tur; gereken kopya 1–15, dugum basina 4 kopya yeni dugumun hazir olma gecikmesi taraniyor: gecikme kapasitesiz tur en uzun seri dugum siparisi dugum-tur kopya-tur 0 3 1 3 302 1003 1 3 1 3 302 1003 2 5 2 6 319 1001 4 10 4 13 431 997 6 10 6 21 837 998 8 8 8 33 2353 1002 uc olcekleme turu bir arada (hazir olma gecikmesi 4): ayar olcekleme olayi kapasitesiz tur yeniden baslatma dugum-tur yalniz yatay (dugum bol) 36 3 0 302 yatay + kume 42 10 0 431 yatay + kume + dikey 54 8 12 445 dikey eklenince: olcekleme olayi 42 -> 54, dugum siparisi 13 -> 13, dugum-tur 431 -> 445
Gecikme Kapasitesizliği Kaynağa Çeviriyor
İkinci sütun beklendiği gibi davranıyor: en uzun kapasitesiz seri, hazır olma gecikmesinin ta kendisidir. Gecikme 4 turken en uzun kesintisiz yetersizlik 4 tur, gecikme 6 turken 6 turdur. Yeni düğüm yola çıkana kadar yük bekler ve bekleme süresi bir tasarım tercihinin değil, düğüm hazırlama süresinin sonucudur.
Birinci sütun beklenmedik davranıyor. Gecikme 6’da 10 tur kapasitesiz kalınırken gecikme 8’de bu sayı 8’e iniyor. Sistemin daha iyi çalıştığı sonucu yanlış olur; dördüncü sütun asıl olanı söylüyor. Düğüm siparişi 13’ten 33’e, düğüm-tur 431’den 2.353’e çıkıyor. Gecikme büyüdükçe denetleyici aynı açığı defalarca görüp defalarca düğüm sipariş ediyor; sonunda kümede ihtiyacın çok üstünde düğüm birikiyor ve kapasitesizlik kaynak harcanarak kapanıyor. Küçültme kuralı beş turda bir düğüm çıkardığı için bu fazlalık koşum boyunca eriyip bitmiyor. Kapasitesiz tur ile düğüm-tur birlikte okunmadıkça gecikme iyileşiyormuş gibi görünür.
Kopya-tur sütununun beş satırda da 1.000 civarında kalması ayrı bir sonuçtur: çalışan kopya sayısı neredeyse hiç değişmiyor, değişen şey o kopyaların ne kadar geç yerleşebildiği ve arkalarında kaç düğümün beklediğidir.
Üç Kol Aynı Anda Çevrilince
Son tablo üç ölçekleme türünü üst üste koyuyor. Düğüm bolken yalnız yatay ölçekleme 36 ölçekleme olayı ve 3 kapasitesiz tur üretiyor. Küme ölçeklemesi eklendiğinde olay sayısı 42’ye, kapasitesiz tur 10’a, düğüm-tur 302’den 431’e çıkıyor: yatay denetleyicinin verdiği karar artık anında uygulanamadığı için kendini tekrarlıyor.
Dikey boyutlandırma eklendiğinde bozulma açıkça sayılabiliyor. On iki yeniden başlatma, ölçekleme olayını 42’den 54’e çıkarıyor — fazladan on iki olay, tam olarak yeniden başlatma sayısı kadar. Zincir şudur: dikey boyutlandırma bir kopyayı iki tur hizmet dışı bırakır, hizmet veren kopya sayısı düşer, kalanların doluluğu yükselir, yatay denetleyici yükün arttığını sanıp kopya ekler, eklenen kopya düğüme sığmazsa küme ölçekleyici düğüm sipariş eder. Gerçek yük bu süre boyunca hiç değişmemiş, düğüm-tur 431’den 445’e çıkmıştır.
Üç denetleyicinin hiçbiri hata yapmıyor. Her biri kendi ölçütünü doğru okuyor ve kendi kuralını doğru uyguluyor. Sorun, birinin eyleminin ötekinin ölçüsü olmasıdır: dikey boyutlandırmanın yeniden başlatması, yatay denetleyicinin doluluk ölçütüne yük artışı olarak girer. Sistemin görmediği kalem burada da tek bir şeydir — bir kopyanın hizmet dışı olmasının nedeni. Bu kalem ölçüte eklenseydi, yani hizmet dışı kopyalar doluluk hesabından çıkarılsaydı, on iki olayın on ikisi de doğmazdı.
Üç kolun bilgi maliyeti de eşit değildir. Yatay ölçekleme kopya başına tek bir doluluk ölçütüyle çalışır ve verdiği karar bir sayaç değişikliğiyle geri alınır. Dikey boyutlandırma kapsül başına bir kullanım penceresi ister — bu modelde altı kapsül için onar turluk pencere, yani her turda altmış örnek — ve kararının bedeli bir yeniden başlatmadır. Küme ölçeklemesi bu ikisinin üstüne düğüm hazırlama süresini ekler; o süre ölçülmez, bildirilir, ve yanlış bildirildiğinde kapasitesiz tur sayısı ile düğüm-tur birlikte kayar.
Özet
- Dikey boyutlandırmanın kazancı boş kapasitede ölçülür: sabit istekte boş oran yüzde 50,1 iken yüzde 20 eşiğiyle yüzde 13,2’ye iniyor, boş istek 369.532’den 54.704 birim-tura düşüyor.
- Bedeli yeniden başlatmadır ve eşik daraldıkça yalnız bedel büyüyor: yüzde 20’de 38 yeniden başlatma ve 76 hizmet dışı tur, yüzde 5’te 141 yeniden başlatma ve 280 hizmet dışı tur, kazanç ise yüzde 13,7’de aynı yerde kalıyor.
- Sıkı boyutlandırma boş kapasiteyi yetersizliğe çevirir: yetersiz tur sıfırdan 190’a, yüzde 50 eşiğinde 336’ya çıkıyor.
- Küme ölçeklemesinde en uzun kapasitesiz seri hazır olma gecikmesine eşittir; gecikme 8’de kapasitesiz tur 8’e inerken düğüm siparişi 13’ten 33’e, düğüm-tur 431’den 2.353’e çıkıyor, yani kapasitesizlik kaynakla kapatılıyor.
- Üç kol birlikte çevrildiğinde on iki yeniden başlatma tam on iki fazladan ölçekleme olayı üretiyor ve düğüm-tur 431’den 445’e çıkıyor; gerçek yük hiç değişmemiştir.
- Üç denetleyici de kendi kuralını doğru uygular; bozulmanın kaynağı birinin eyleminin ötekinin ölçütüne yük olarak girmesi ve hizmet dışı kalma nedeninin ölçütte bulunmamasıdır.
Sonraki Adım
Bu konu yerleştirme ve büyütme kararlarını sayıya bağladı: istek ve sınır, kısıtlar, işaretler, tahliye, üç ölçekleme türü. Hepsinin ortak varsayımı, istenen durumun bir yerde yazılı olduğu ve kümenin onu uygulamaya çalıştığıdır. O istenen durumun nasıl yayına alındığı, kapsülün ne zaman sağlıklı sayıldığı, hangi öznenin hangi nesnede yetkili olduğu, ağın kimden kime açık olduğu ve bir arıza anında bütün bunların nasıl geri alındığı henüz sorulmadı. Sonraki konu kümenin işletimini ele alır: dağıtım kalıpları, denetim türleri, yetki ve ağ politikası, izleme, sorun giderme ve kümenin kendi nesne türleriyle genişletilmesi.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.