Ders 01 / 20
Sunucusuz Kavramı
Aynı günün iş yükü iki düzende koşturulur: sürekli çalışan örnek ile isteğe göre çağrılan işlev; boşta geçen kapasite, tepe anında karşılanan istek ve gece işinin bittiği saat yan yana sayılır, taban yük sıfırdan altmış beş bine taranarak başabaş yük düzeyi çıkarılır ve devredilen on karar ile karşılığında gelen sekiz sayılı kısıt tek defterde toplanır.
İçindekiler
Önceki kurs makineyi, ağı ve veriyi tek tek kiraladı. Her kiralamada aynı şey oldu: bir karar sağlayıcıya geçti, karşılığında bir kısıt geldi. Ama üç kursun sonunda bile altta duran şey değişmedi — kiralanan kapasite sürekli çalışan bir sunucudur ve iş gelmediği saatlerde de sayaç işler. Bu kursun sorusu odur: kapasitenin kendisi de isteğe göre kiralanabilir mi.
Ölçü tek eksende ilerler: aynı gün, aynı iş yükü, iki düzen. Birincide örnek sayısına karar veren taraf elde kalır, ikincide o karar sağlayıcıdadır. Fark yalnız faturada değildir — boşta duran kapasite, tepede karşılanan istek ve gece işinin bittiği saat de değişir.
IH1. Bölgesel ölçüm ağı, su sayaçlarından okuma toplayan, okumaları doğrulayan, fatura üreten ve saha ekiplerine bildirim gönderen kurgu bir yazılımdır; bütün süreler, sayılar ve fiyatlar kurgudur. IH2. Bir okuma doğrulaması 400 ms tutar; sürekli çalışan bir örnek aynı anda dört doğrulama taşır: dakikada 600 istek. IH3. Fiyatlar kurgu bir ölçüyle — birim — yazılır ve gerçek para birimi değildir: örnek-dakika 0,6 birim, işlev çağrısı 0,0005 birim, 400 ms işlem 0,001 birim. IH4. Günün trafiği kendi yazılan bir üreteçle kurulur ve tohum 20260802’dir. IH5. Sürekli düzende örnek sayısı gün boyu sabittir; kapasiteyi aşan istek düşmez, kuyrukta bekler. IH6. İşlev düzeninde her istek geldiği dakikada çalışır ve hesap düzeyindeki eşzamanlılık sınırı 200’dür.
Aynı Günün İki Düzeni
Ölçüm ağının günü düz değildir: okumalar gece toplu işlenir, fatura sabaha karşı üretilir, doğrulama trafiği gündüz akar, saha bildirimi hiç durmaz. Aşağıdaki model günü dakika dakika kurar.
// olcum-agi/iki-duzen.mjs — ayni gunun yuku iki duzende: surekli ornek ve istege gore islev (model) // Butun birimler kurgudur; "birim" hayali bir olcu, gercek para degildir. export const DK = 1440, ISLEM_MS = 400, ESZAMAN = 4; export const ORNEK_KAP = 60000 * ESZAMAN / ISLEM_MS; // bir ornek dakikada 600 istek export const ORNEK_DK = 0.6, CAGRI = 0.0005, SURE = 0.001; // birim export const ISTEK_BIRIM = CAGRI + SURE; export const uretec = (t) => { let s = t >>> 0; return () => { s ^= s << 13; s >>>= 0; s ^= s >>> 17; s ^= s << 5; s >>>= 0; return s / 4294967296; }; }; // Bolgesel olcum aginin kurgu gunu: gece toplu okuma islemesi, sabah fatura, gunduz dogrulama. export const trafik = (taban = 0, tohum = 20260802) => { const r = uretec(tohum), y = new Array(DK).fill(0); for (let d = 0; d < DK; d++) { let v = taban + 60; // saha bildirimi: her dakika akar if (d >= 360 && d < 1320) v += 700 * (0.75 + 0.5 * r()); // okuma dogrulama trafigi if (d >= 120 && d < 145) v += 22000; // gece toplu okuma islemesi if (d >= 300 && d < 310) v += 6000; // fatura uretimi y[d] = Math.round(v); } return y; }; export const saat = (d) => `${String(Math.floor(d / 60)).padStart(2, "0")}:${String(d % 60).padStart(2, "0")}`; // Surekli duzen: ornek sayisi gun boyu sabit; asan istek kuyrukta bekler. export const surekli = (y, ornek) => { const kap = ornek * ORNEK_KAP; let kuyruk = 0, enUzun = 0, bitis = -1; for (let d = 0; d < DK; d++) { kuyruk += y[d] - Math.min(kuyruk + y[d], kap); if (kuyruk > enUzun) enUzun = kuyruk; if (d >= 145 && kuyruk === 0 && bitis < 0) bitis = d; } const toplam = y.reduce((a, b) => a + b, 0); return { ad: `surekli ${ornek} ornek`, maliyet: ornek * DK * ORNEK_DK, yuva: ornek * DK * ORNEK_KAP, kullanim: toplam / (ornek * DK * ORNEK_KAP), tepede: Math.min(Math.max(...y), kap), enUzun, devreden: kuyruk, bitis }; }; // Islev duzeni: kapasite karari devredildi; her istek geldigi dakikada calisir. export const islev = (y) => { const toplam = y.reduce((a, b) => a + b, 0), tepe = Math.max(...y); return { ad: "islev", maliyet: toplam * ISTEK_BIRIM, yuva: toplam, kullanim: 1, tepede: tepe, enUzun: 0, devreden: 0, bitis: 144, eszaman: Math.ceil(tepe * (ISLEM_MS / 1000) / 60) }; }; if (import.meta.url === `file://${process.argv[1]}`) { const y = trafik(), toplam = y.reduce((a, b) => a + b, 0), tepe = Math.max(...y); console.log(`gun: ${toplam} istek, tepe ${tepe} istek/dk, ortalama ${Math.round(toplam / DK)} istek/dk, ` + `tepe/ortalama ${(tepe / (toplam / DK)).toFixed(1)}`); const duzenler = [surekli(y, Math.ceil(tepe / ORNEK_KAP)), surekli(y, 12), surekli(y, 2), islev(y)]; console.log("\n" + "duzen".padEnd(20) + "maliyet".padEnd(11) + "bosta yuva".padEnd(13) + "bosta oran".padEnd(12) + "tepede karsilanan".padEnd(19) + "en uzun kuyruk".padEnd(16) + "gece isi biter"); for (const d of duzenler) console.log(d.ad.padEnd(20) + d.maliyet.toFixed(0).padEnd(11) + (d.yuva - toplam).toFixed(0).padEnd(13) + `%${((1 - d.kullanim) * 100).toFixed(1)}`.padEnd(12) + `${d.tepede}/${tepe}`.padEnd(19) + d.enUzun.toFixed(0).padEnd(16) + (d.bitis < 0 ? `bitmiyor (${d.devreden} devreden)` : saat(d.bitis + 1))); const t = duzenler[0], i = duzenler[3]; console.log(`\ntepeye gore boyutlandirma islevden ${(t.maliyet / i.maliyet).toFixed(1)} kat pahali; ` + `islev duzeninde tepede gereken eszamanlilik ${i.eszaman}`); }
gun: 1370625 istek, tepe 22060 istek/dk, ortalama 952 istek/dk, tepe/ortalama 23.2 duzen maliyet bosta yuva bosta oran tepede karsilanan en uzun kuyruk gece isi biter surekli 37 ornek 31968 30597375 %95.7 22060/22060 0 02:26 surekli 12 ornek 10368 8997375 %86.8 7200/22060 371500 03:18 surekli 2 ornek 1728 357375 %20.7 1200/22060 521500 18:48 islev 2056 0 %0.0 22060/22060 0 02:25 tepeye gore boyutlandirma islevden 15.5 kat pahali; islev duzeninde tepede gereken eszamanlilik 148
Sürekli düzenin üç satırı üç ayrı kötü seçenektir. Tepeye göre boyutlandırma her isteği zamanında karşılar ve karşılığında günün %95,7’sinde boş duran 30,6 milyon istek yuvası ödetir; 37 örnek gün boyu ayaktadır, oysa yirmi beş dakika dışında ikisi yeterlidir. Ortalamaya göre boyutlandırma faturayı 31.968 birimden 1.728 birime indirir — ama gece 02:25’te başlayan toplu işleme akşam 18:48’de biter ve gün boyunca 521.500 kayıt kuyrukta bekler. Aradaki 12 örnek uzlaşmadır: maliyet 10.368, gece işi 03:18’de biter, boşta oran hâlâ %86,8’dir.
İşlev satırı üçünün hiçbirine benzemez. Boşta yuva sıfırdır, çünkü boşta duran bir şey yoktur; tepedeki 22.060 isteğin hepsi karşılanır ve gece işi geldiği dakikada — 02:25’te — biter. Fatura tepeye göre boyutlandırmanın on beşte biridir. Fark bir verimlilik hilesi değil, ölçünün yer değiştirmesidir: orada ayakta durma süresi ücretlendirilir, burada yapılan iş.
Son satır kısıtın ilk sayısını verir: tepede 148 eşzamanlı çağrı gerekir, hesap sınırı 200’dür. Örnek sayısına karar verilmez, ama 200 verilmiş bir tavandır ve trafik %35 artsa tepe ona dayanır.
Yük Profili Taraması
Yukarıdaki gün seyrek ve anidir: tepe, ortalamanın 23,2 katıdır. Böyle bir profilde işlevin kazanması şaşırtıcı değildir. Asıl soru profil düzleştikçe ne olduğudur. Aşağıdaki tarama günün üzerine sürekli bir taban yük ekler ve iki düzeni her düzeyde yeniden fiyatlandırır.
// olcum-agi/yuk-taramasi.mjs — surekli taban yuk artarken basabas noktasi nerede (model) import { DK, ORNEK_KAP, ORNEK_DK, ISTEK_BIRIM, trafik, surekli, islev } from "./iki-duzen.mjs"; export const nokta = (taban) => { const y = trafik(taban), toplam = y.reduce((a, b) => a + b, 0), tepe = Math.max(...y); const ornek = Math.ceil(tepe / ORNEK_KAP), s = surekli(y, ornek), i = islev(y); return { taban, tepe, ortalama: toplam / DK, oran: tepe / (toplam / DK), ornek, kullanim: s.kullanim, s: s.maliyet, i: i.maliyet }; }; if (import.meta.url === `file://${process.argv[1]}`) { console.log("taban yuk".padEnd(12) + "tepe/ortalama".padEnd(15) + "ornek".padEnd(8) + "kullanim".padEnd(11) + "surekli".padEnd(10) + "islev".padEnd(10) + "islev/surekli".padEnd(15) + "kazanan"); for (const t of [0, 2000, 5000, 10000, 20000, 30000, 40000, 50000, 65000]) { const n = nokta(t); console.log(`${t}`.padEnd(12) + n.oran.toFixed(1).padEnd(15) + String(n.ornek).padEnd(8) + `%${(n.kullanim * 100).toFixed(1)}`.padEnd(11) + n.s.toFixed(0).padEnd(10) + n.i.toFixed(0).padEnd(10) + (n.i / n.s).toFixed(2).padEnd(15) + (n.i < n.s ? "islev" : "surekli")); } let a = 0, b = 65000; for (let k = 0; k < 24; k++) { const o = (a + b) / 2; (nokta(Math.round(o)).i < nokta(Math.round(o)).s) ? a = o : b = o; } const bb = nokta(Math.round(a)); console.log(`\nbasabas taban yuk: ${Math.round(a)} istek/dk — bu noktada tepe/ortalama ${bb.oran.toFixed(2)}, ` + `kullanim %${(bb.kullanim * 100).toFixed(1)}`); console.log(`kuramsal esik: bir ornegin istek basina bedeli ${(ORNEK_DK / ORNEK_KAP).toFixed(6)} birim, ` + `islevin ${ISTEK_BIRIM.toFixed(6)} birim — orani %${((ORNEK_DK / ORNEK_KAP) / ISTEK_BIRIM * 100).toFixed(1)}`); }
taban yuk tepe/ortalama ornek kullanim surekli islev islev/surekli kazanan 0 23.2 37 %4.3 31968 2056 0.06 islev 2000 8.2 41 %12.0 35424 6376 0.18 islev 5000 4.5 46 %21.6 39744 12856 0.32 islev 10000 2.9 54 %33.8 46656 23656 0.51 islev 20000 2.0 71 %49.2 61344 45256 0.74 islev 30000 1.7 87 %59.3 75168 66856 0.89 islev 40000 1.5 104 %65.6 89856 88456 0.98 islev 50000 1.4 121 %70.2 104544 110056 1.05 surekli 65000 1.3 146 %75.3 126144 142456 1.13 surekli basabas taban yuk: 42248 istek/dk — bu noktada tepe/ortalama 1.49, kullanim %66.7 kuramsal esik: bir ornegin istek basina bedeli 0.001000 birim, islevin 0.001500 birim — orani %66.7
Tarama tek bir kural gösterir: işlevin kazanması trafiğin büyüklüğüne değil biçimine bağlıdır. Taban yük sıfırken işlev on altı kat ucuzdur, 42.248 istek/dk’da iki düzen eşitlenir, ötesinde sürekli düzen kazanır. Başabaş kullanım oranı %66,7’dir ve rastgele değildir — son satır aynı oranı fiyattan türetir: bir örnek istek başına 0,001, işlev 0,0015 birim tutar.
Kural bir tercihe değil bir ölçüme dayanır: kapasitenin üçte ikisi sürekli dolu değilse kapasiteyi kendi yönetmek pahalıdır. Tepe/ortalama sütunu aynı sınırı ikinci bir açıdan verir; oran 1,5’in altına indiğinde işlevin üstünlüğü biter.
Devredilen Kararın Defteri
Fatura tablonun yalnız bir sütunudur. Asıl değişen, kararların kimde durduğudur.
// olcum-agi/karar-defteri.mjs — hangi karar devredildi, karsiliginda hangi sayi geldi (model) import { ISLEM_MS, ORNEK_DK, trafik, islev } from "./iki-duzen.mjs"; // [karar, surekli duzende, islev duzeninde, gelen kisit (kurgu sayi)] export const KARAR = [ ["ornek sayisi", "sende", "saglayicida", "eszamanlilik siniri 200"], ["olcekleme esigi", "sende", "saglayicida", "olcekleme adimi 60 ornek/dk"], ["makine boyutu", "sende", "saglayicida", "bellek kademesi 128-3008"], ["bir isin ust suresi", "sende", "saglayicida", "sure siniri 900 sn"], ["yerel disk", "sende", "saglayicida", "gecici alan 512 birim"], ["paket icerigi", "sende", "kismen sende", "paket boyutu 250 birim"], ["calisma zamani surumu", "sende", "kismen sende", "destek penceresi 24 ay"], ["isletim sistemi yamasi", "sende", "saglayicida", "yama takvimi gorunmez"], ["yerlestirme", "sende", "saglayicida", "bolge secilir, makine secilmez"], ["ornegin ne kadar yasayacagi", "sende", "saglayicida", "bosta 300 sn sonra geri alinir"], ["istek basina fiyat", "saglayicida", "saglayicida", "—"], ]; // [kisit, kisitin etrafindan dolasma yolu] export const DOLASMA = [["sure siniri 900 sn", "isi parcala"], ["eszamanlilik siniri 200", "pay rezerve et"], ["bosta 300 sn sonra geri alinir", "onceden isit"], ["gecici alan 512 birim", "durumu disari al"]]; if (import.meta.url === `file://${process.argv[1]}`) { console.log("karar".padEnd(30) + "surekli duzen".padEnd(16) + "islev duzeni".padEnd(16) + "karsiligindaki kisit"); for (const [a, s, i, k] of KARAR) console.log(a.padEnd(30) + s.padEnd(16) + i.padEnd(16) + k); const say = (j) => KARAR.filter((x) => x[j].includes("sende")).length; const sayili = KARAR.filter((x) => x[2] !== "sende" && /\d/.test(x[3])).length; console.log(`\nsurekli duzende ${say(1)} karar elde, islev duzeninde ${say(2)} karar tam ya da kismen elde; ` + `${say(1) - say(2)} karar bastan devredildi, ${sayili} kisit bir sayiyla geri geldi`); const y = trafik(), gece = y.slice(120, 145).reduce((a, b) => a + b, 0); const tek = gece * (ISLEM_MS / 1000), isit = 8, bosta = isit * 1440, ez = islev(y).eszaman; const BEDEL = [ `${gece} kayitlik gece isi tek parcada ${Math.round(tek)} sn; sinira sigmasi icin ${Math.ceil(tek / 900)} cagri`, `tepede gereken ${ez} rezerve edilirse otekilere ${200 - ez} eszamanlilik kalir`, `${isit} ornek surekli sicak tutulursa gunde ${bosta} bosta ornek-dakika, ${(bosta * ORNEK_DK).toFixed(0)} birim`, `her cagri durumu disaridan okur: ${y.reduce((a, b) => a + b, 0)} ek okuma-yazma cifti`]; console.log("\n" + "kisit".padEnd(32) + "dolasma yolu".padEnd(20) + "bedeli"); DOLASMA.forEach(([k, yol], j) => console.log(k.padEnd(32) + yol.padEnd(20) + BEDEL[j])); }
karar surekli duzen islev duzeni karsiligindaki kisit ornek sayisi sende saglayicida eszamanlilik siniri 200 olcekleme esigi sende saglayicida olcekleme adimi 60 ornek/dk makine boyutu sende saglayicida bellek kademesi 128-3008 bir isin ust suresi sende saglayicida sure siniri 900 sn yerel disk sende saglayicida gecici alan 512 birim paket icerigi sende kismen sende paket boyutu 250 birim calisma zamani surumu sende kismen sende destek penceresi 24 ay isletim sistemi yamasi sende saglayicida yama takvimi gorunmez yerlestirme sende saglayicida bolge secilir, makine secilmez ornegin ne kadar yasayacagi sende saglayicida bosta 300 sn sonra geri alinir istek basina fiyat saglayicida saglayicida — surekli duzende 10 karar elde, islev duzeninde 2 karar tam ya da kismen elde; 8 karar bastan devredildi, 8 kisit bir sayiyla geri geldi kisit dolasma yolu bedeli sure siniri 900 sn isi parcala 551500 kayitlik gece isi tek parcada 220600 sn; sinira sigmasi icin 246 cagri eszamanlilik siniri 200 pay rezerve et tepede gereken 148 rezerve edilirse otekilere 52 eszamanlilik kalir bosta 300 sn sonra geri alinir onceden isit 8 ornek surekli sicak tutulursa gunde 11520 bosta ornek-dakika, 6912 birim gecici alan 512 birim durumu disari al her cagri durumu disaridan okur: 1370625 ek okuma-yazma cifti
On bir kararın onu sürekli düzende eldedir; işlev düzeninde elde kalan iki tanedir ve ikisi de yalnız kısmen — paketin içeriği paket boyutu sınırına, çalışma zamanının sürümü destek penceresine takılır. Sekiz karar baştan devredilir ve sekizi de bir sayıyla geri döner. Devretmek kararı ortadan kaldırmaz; kararı bir tavana çevirir.
Alt tablo o tavanların etrafından dolaşma yollarını fiyatlandırır. Gece toplu işi tek parçada 220.600 saniye tutar; 900 saniyelik sınıra sığması için 246 ayrı çağrıya bölünmesi gerekir ve 246 çağrı, tek işin sürdürmediği bir ilerleme kaydı ile kısmi başarı sorusu demektir. Tepedeki 148 eşzamanlılık rezerve edilirse ölçüm ağının öteki bütün işlevlerine 52 kalır: bir işlevi korumak ötekileri aç bırakır. Sekiz örneği sürekli sıcak tutmak günde 11.520 boşta örnek-dakika, yani 6.912 birim eder — kaçınılan boşta kapasitenin küçük ölçekte geri alınması.
Dört satırın ortak biçimi şudur: kısıt bir sayıdır, dolaşma yolu vardır ve dolaşmanın bedeli kısıtın ölçüldüğü birimde değildir. Süre sınırından çağrı sayısına, eşzamanlılık sınırından öteki işlevlerin payına, örnek ömründen boşta kapasiteye geçilir; her kısıt kendi cinsinden ödenir.
Özet
- Tepeye göre boyutlandırılmış sürekli düzen 31.968 birim ve %95,7 boşta kapasite, işlev düzeni 2.056 birim ve sıfır boşta kapasite ödetti — on beş kat fark.
- Ucuzlatmak için örnek sayısını 2’ye indirmek faturayı 1.728 birime çekti ama 02:25’te başlayan gece işini 18:48’e taşıdı ve 521.500 kaydı kuyrukta bıraktı; ucuzluk gecikmeyle ödendi.
- Taban yük taraması başabaş noktasını 42.248 istek/dk’da buldu: kullanım %66,7 ve tepe/ortalama 1,49. Kapasitenin üçte ikisi sürekli dolu değilse kapasiteyi kendi yönetmek pahalıdır.
- On bir kararın onu sürekli düzende elde, işlev düzeninde yalnız ikisi kısmen elde kaldı; sekiz devredilen kararın sekizi de sayılı bir kısıt olarak geri geldi.
- Dolaşmanın bedeli hep başka bir birimdedir: süre sınırı 246 çağrıya, örnek ömrü günde 11.520 boşta örnek-dakikaya, eşzamanlılık sınırı ötekilere kalan 52 paya çevrilir.
Sonraki Adım
Bu ders işlevi tek bir biçimde çağırdı: istek geldi, işlev çalıştı, sonuç döndü. Oysa gece toplu işlemesiyle saha bildirimi aynı yolla çağrılmak zorunda değildir — biri sonucu bekleyen bir istemcinin ucundadır, öteki bir kuyruğun.
Sonraki ders aynı doğrulama işini üç çağırma modelinde koşturur ve dört şeyi ayrı sayar: çağıranın gördüğü gecikme, hatanın çağırana görünüp görünmediği, yeniden denemenin kimde olduğu ve aynı kaydın iki kez işlenme riski. Ardından toplu okuma boyutu taranır: boy büyüdükçe verim artarken tek bozuk kaydın kaç sağlam kaydı birlikte durdurduğu ölçülür.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.