Ders 06 / 12
İstek Üzerine Ortam Sağlama
Aynı doksan günlük talep akışı iki yoldan geçirilir: insanın kurduğu talep kuyruğu ve istek üzerine üretilen ortam. Bekleme süresi, ortam ömrü, boşta duran ortam-günü ve unutulan ortam sayılır; ömür sınırı taranarak kısa ömrün yeniden kurma ve veri kaybı karşılığı çıkarılır.
İçindekiler
Önceki konu platformun ne olduğunu tanımladı ve sınırlarını çizdi: hangi kararın devralındığı, hangisinin ekipte kaldığı, iç müşterinin kim olduğu. Tanım yerinde duruyor, ama bir ekip sabah işe başladığında platformdan somut olarak ne isteyeceği hâlâ söylenmedi. İstenecek ilk şey neredeyse her zaman aynıdır: üzerinde çalışılacak bir ortam.
İstek üzerine ortam, bir ekibin ortam kurulumunu bir talep formuna yazıp beklemek yerine kendi başlattığı ve kendi bitirdiği ortamdır. Ortamın nasıl sağlandığı — bildirimden gerçeğe giden yol, kayıt ile gerçek arasındaki sapma — M22/K01’in ortam sağlama dersinde ve M22/K05’te ölçüldü; burada tekrarlanmaz. Bu dersin ölçtüğü şey sağlama mekaniği değil, ortamın yaşam döngüsüdür: ne kadar beklendiği, ne kadar yaşadığı ve yaşadığı sürenin ne kadarında kullanılmadığı.
Ölçüm bölgesel ölçüm ağı üzerindedir: su sayacı okumalarını toplayan, doğrulayan ve saha iş emri
açan kurgu yazılım. Gerçek altyapı kurulmaz; ölçülen şey node ile yazılmış bir modeldir.
PT1. Ağın yazılımını beş ekip üretir: sayaç okuma, doğrulama, faturalama, saha, raporlama. Ekipler ve talep oranları kurgudur. PT2. Gözlem penceresi 90 gündür. Talep akışı kendi yazılan bir üreteçle çıkarılır; tohum görünürdür. PT3. Elle ortam kurmak 6 saat insan emeğidir ve platform ekibinin elle kurma kapasitesi günde bir ortamdır. PT4. İstek üzerine yolda üretim 0,5 saat sürer; eş zamanlı açık ortam havuzu 16’dır. PT5. Kuyruk yolunda teslim edilen ortam kapatılmaz — yeniden beklemek pahalıdır. İstek üzerine yolda ekip kullanımı bitince kapatır; kapatmayı unuttuğu durumlar önceden yazılıdır, rastgelelik yoktur. PT6. Platform iki ortam biçimi sunar: küçük ve orta. Alan donanımlı biçim sunulmaz. Unutulan ortam, son kullanım gününden sonra en az yedi gün açık kalan ortamdır.
Talep Kuyruğu ve İstek Üzerine
// veri.mjs — bes ekibin doksan gunluk ortam talebi; model, uretec kendi yazildi, tohum gorunur. export const EKIP = ["sayac-okuma", "dogrulama", "faturalama", "saha", "raporlama"]; export const GUN = 90, TOHUM = 20260801; export const uretec = (t) => () => ((t = (t * 1103515245 + 12345) % 2147483648) / 2147483648); const ORAN = { "sayac-okuma": 0.24, dogrulama: 0.16, faturalama: 0.10, saha: 0.30, raporlama: 0.06 }; const BICIM = { "sayac-okuma": "kucuk", dogrulama: "orta", faturalama: "orta", saha: "alan-donanimli", raporlama: "orta" }; // platform yalniz kucuk ve orta sunuyor export const SUNULAN = ["kucuk", "orta"]; export const talepler = () => { // her ekip icin gun gun bagimsiz cekilis const r = uretec(TOHUM), t = []; for (let g = 0; g < GUN; g++) for (const e of EKIP) { const [a, b, c] = [r(), r(), r()]; if (a < ORAN[e]) t.push({ ekip: e, gun: g, bicim: BICIM[e], kullanim: 1 + Math.floor(b * 9), // fiilen kac gun kullanilacak durumlu: c < 0.45 }); // ortamda uretilmis veri kaliyor mu } return t; };
Aynı talep akışı iki yoldan geçirilir. Kuyruk yolunda her talebi insan karşılar. Platform yolunda sunulan biçimdeki talepler istek üzerine üretilir; sunulmayan biçimdekiler altın yolun dışında kalır ve o ekip ortamını kendi kurar.
// yol.mjs — ayni talep akisi iki yoldan gecirilir: talep kuyrugu ve istek uzerine ortam. import { talepler, GUN, EKIP, SUNULAN } from "./veri.mjs"; const KAPASITE = 1, HAVUZ = 16, URETIM_SAAT = 0.5, ELLE_SAAT = 6, UNUT = 7; const T = talepler(); const ort = (d) => (d.length ? d.reduce((a, b) => a + b, 0) / d.length : 0).toFixed(1); const kuyruk = (liste) => { // insan kurar: gunde en cok bir ortam const bekleyen = [], ortam = []; for (let g = 0; g < GUN; g++) { bekleyen.push(...liste.filter((t) => t.gun === g)); for (let k = 0; k < KAPASITE && bekleyen.length; k++) { const t = bekleyen.shift(); ortam.push({ ...t, acilis: g, bekleme: (g - t.gun) * 24 + ELLE_SAAT, kapanis: GUN }); } // kuyruk yolunda ortam biraktirilmaz } return { ortam, teslimsiz: bekleyen.length, dolu: 0 }; }; const istekUzerine = (liste) => { // bir istekle uretilir, havuz sinirli const bekleyen = [], ortam = [], acik = []; let dolu = 0; for (let g = 0; g < GUN; g++) { for (let i = acik.length - 1; i >= 0; i--) if (acik[i].kapanis <= g) acik.splice(i, 1); bekleyen.push(...liste.filter((t) => t.gun === g)); while (bekleyen.length && acik.length < HAVUZ) { const t = bekleyen.shift(); const unutuldu = (t.gun * 7 + t.kullanim) % 4 === 0; // onceden yazili, rastgele degil const o = { ...t, acilis: g, bekleme: (g - t.gun) * 24 + URETIM_SAAT, unutuldu, kapanis: unutuldu ? GUN : Math.min(GUN, g + t.kullanim) }; ortam.push(o); acik.push(o); } if (acik.length >= HAVUZ) dolu++; } return { ortam, teslimsiz: bekleyen.length, dolu }; }; const kendiKuran = (liste) => ({ dolu: 0, teslimsiz: 0, // dis yolda ekip kendi kurar, kapatmaz ortam: liste.map((t) => ({ ...t, acilis: t.gun, bekleme: ELLE_SAAT, kapanis: GUN })) }); const olc = (ad, { ortam, teslimsiz, dolu }) => { const gun = ortam.reduce((a, o) => a + (o.kapanis - o.acilis), 0); const kullanilan = ortam.reduce((a, o) => a + Math.min(o.kullanim, o.kapanis - o.acilis), 0); const unutulan = ortam.filter((o) => o.kapanis - o.acilis - o.kullanim >= UNUT).length; console.log(`${ad.padEnd(20)} teslim ${String(ortam.length).padStart(2)}` + ` teslimsiz ${teslimsiz} bekleme ${ort(ortam.map((o) => o.bekleme)).padStart(5)} saat` + ` ortam-gun ${String(gun).padStart(4)} bosta ${String(gun - kullanilan).padStart(4)}` + ` (%${String(Math.round((gun - kullanilan) / gun * 100)).padStart(2)}) unutulan ${unutulan}`); return { gun, kullanilan, unutulan, dolu, n: ortam.length }; }; const ic = T.filter((t) => SUNULAN.includes(t.bicim)); const dis = T.filter((t) => !SUNULAN.includes(t.bicim)); console.log(`talep ${T.length} pencere ${GUN} gun ekip ${EKIP.length} elle kurulum ` + `${ELLE_SAAT} saat, ${KAPASITE}/gun havuz ${HAVUZ} es zamanli uretim ${URETIM_SAAT} saat`); const A = olc("talep kuyrugu (hep)", kuyruk(T)); const B = olc("istek uzerine (ic)", istekUzerine(ic)); const C = olc("altin yol disinda", kendiKuran(dis)); console.log(`havuzun dolu oldugu gun ${B.dolu}/${GUN}; havuz doluyken gelen talep bekliyor,` + ` ${B.dolu ? "gizlenen kapasite geri siziyor" : "sizma yok"}`); console.log(`altin yol disinda ${dis.length}/${T.length} talep, tek gerekce alan-donanimli bicim` + ` (${[...new Set(dis.map((t) => t.ekip))].join(", ")}); platform hizmetinden hicbiri yararlanmiyor`); console.log(`insan emegi: kuyruk ${A.n * ELLE_SAAT} saat platform ${C.n * ELLE_SAAT} saat` + ` (yalnizca dis yol) kurtulan ${(A.n - C.n) * ELLE_SAAT} saat`);
talep 90 pencere 90 gun ekip 5 elle kurulum 6 saat, 1/gun havuz 16 es zamanli uretim 0.5 saat talep kuyrugu (hep) teslim 83 teslimsiz 7 bekleme 83.2 saat ortam-gun 3528 bosta 3133 (%89) unutulan 73 istek uzerine (ic) teslim 60 teslimsiz 3 bekleme 10.1 saat ortam-gun 877 bosta 580 (%66) unutulan 12 altin yol disinda teslim 27 teslimsiz 0 bekleme 6.0 saat ortam-gun 1212 bosta 1090 (%90) unutulan 22 havuzun dolu oldugu gun 16/90; havuz doluyken gelen talep bekliyor, gizlenen kapasite geri siziyor altin yol disinda 27/90 talep, tek gerekce alan-donanimli bicim (saha); platform hizmetinden hicbiri yararlanmiyor insan emegi: kuyruk 498 saat platform 162 saat (yalnizca dis yol) kurtulan 336 saat
Bekleme farkı en görünür sayıdır: kuyruk yolunda ortalama 83,2 saat, istek üzerine yolda 10,1 saat. Kuyruk yolunda 90 talebin 7’si pencere kapandığında hâlâ sıradadır. Ama beklemeyi düşüren şey tek başına otomasyon değildir; kuyruk yolunun kapasitesi günde bir ortamdır ve talep günde bir taleptir, yani kuyruk zaten doygunluk sınırında çalışır. Devredilen karar şudur: ortamın ne zaman var olacağına ve ne zaman yok olacağına insan değil, ekip kendi karar verir.
İkinci sayı ilkinden daha ilginçtir. Kuyruk yolunda 3.528 ortam-günün 3.133’ü boştadır, yani ortamlar ömürlerinin yüzde 89’unda kullanılmamaktadır. Nedeni beklemededir: ortam almak günler sürdüğü için kimse aldığı ortamı geri vermez, ve 83 ortamın 73’ü unutulan ortama dönüşür. Bekleme süresi ile boşta duran kaynak birbirinden bağımsız iki sorun değildir; biri diğerini üretir.
Ömür Sınırı: Kısa Ömrün Karşılığı
// omur.mjs — omur siniri taranir: maliyet, yeniden kurma, veri kaybi; sonra esik hesaplanir. import { talepler, GUN, EKIP, SUNULAN } from "./veri.mjs"; const HAVUZ = 16, ELLE_SAAT = 6, UNUT = 7, KURULUM = 320, ISLETME_AY = 8, AY = 3; const T = talepler(), ic = T.filter((t) => SUNULAN.includes(t.bicim)); const tara = (omur) => { // omur dolunca ortam silinir, is bitmediyse geri istenir const bekleyen = [], acik = []; let gunToplam = 0, uretilen = 0, yeniden = 0, kayip = 0, unutulan = 0; for (let g = 0; g < GUN; g++) { for (let i = acik.length - 1; i >= 0; i--) { const o = acik[i], yas = g - o.acilis, bitti = o.kalan === 0 && !o.unutuldu; if (!bitti && yas < omur) continue; acik.splice(i, 1); gunToplam += yas; if (yas - (o.kullanim - o.kalan) >= UNUT) unutulan++; if (o.kalan > 0) { yeniden++; kayip += o.durumlu ? 1 : 0; bekleyen.push(o); } } bekleyen.push(...ic.filter((t) => t.gun === g).map((t) => ({ ...t, kalan: t.kullanim, unutuldu: (t.gun * 7 + t.kullanim) % 4 === 0 }))); while (bekleyen.length && acik.length < HAVUZ) { acik.push({ ...bekleyen.shift(), acilis: g }); uretilen++; } for (const o of acik) if (o.kalan > 0) o.kalan--; } for (const o of acik) { // pencere sonunda hala acik olanlar gunToplam += GUN - o.acilis; if (GUN - o.acilis - (o.kullanim - o.kalan) >= UNUT) unutulan++; } return { gunToplam, uretilen, yeniden, kayip, unutulan, teslimsiz: bekleyen.length }; }; console.log("omur ortam-gun uretilen yeniden kurma veri kaybi unutulan teslimsiz"); for (const s of [1, 2, 3, 5, 7, 14, 90]) { const r = tara(s); console.log(`${(s === 90 ? "yok" : s + " gun").padEnd(7)}${String(r.gunToplam).padStart(6)}` + `${String(r.uretilen).padStart(10)}${String(r.yeniden).padStart(15)}` + `${String(r.kayip).padStart(12)}${String(r.unutulan).padStart(10)}${String(r.teslimsiz).padStart(11)}`); } const fayda = Object.fromEntries(EKIP.map((e) => // ekip basina kurtulan insan-saat [e, ic.filter((t) => t.ekip === e).length * ELLE_SAAT])); const bedel = KURULUM + ISLETME_AY * AY; let k = 0, esik = 0; const yigin = EKIP.map((e) => { k += fayda[e]; if (k >= bedel && !esik) esik = EKIP.indexOf(e) + 1; return `${e} ${fayda[e]} (${k})`; }); console.log(`\nplatform bedeli ${bedel} insan-saat (kurulum ${KURULUM} + ${AY} ay isletme)` + ` bes ekibin toplam kazanci ${k} insan-saat`); console.log(`ekip basina kurtulan (yigisik): ${yigin.join(" ")}`); console.log(`esik ${esik ? esik + ". ekipte asiliyor" : "bu donemde asilmiyor"}` + `; katki veren ekip ${EKIP.filter((e) => fayda[e] > 0).length}/${EKIP.length}`);
omur ortam-gun uretilen yeniden kurma veri kaybi unutulan teslimsiz 1 gun 314 314 251 113 0 0 2 gun 322 175 112 50 0 0 3 gun 331 127 64 27 0 0 5 gun 343 90 27 12 0 0 7 gun 355 76 13 8 0 0 14 gun 425 63 0 0 10 0 yok 877 60 0 0 12 3 platform bedeli 344 insan-saat (kurulum 320 + 3 ay isletme) bes ekibin toplam kazanci 378 insan-saat ekip basina kurtulan (yigisik): sayac-okuma 174 (174) dogrulama 78 (252) faturalama 90 (342) saha 0 (342) raporlama 36 (378) esik 5. ekipte asiliyor; katki veren ekip 4/5
Tarama iki eğrinin farklı hızda gittiğini gösterir. Ömür sınırı yokken 877 ortam-gün harcanır; sınır on dört güne çekildiğinde bu sayı 425’e, yani yarısının altına iner ve karşılığında hiçbir yeniden kurma doğmaz. Buradan sonrası aynı ucuz değildir: on dört günden yedi güne inmek maliyeti yalnızca 425’ten 355’e çeker, ama 13 yeniden kurma ve 8 veri kaybı olayı üretir. Bir güne inmek maliyeti 314’e indirir — yedi güne göre yüzde on iki kazanç — ve karşılığında 251 yeniden kurma ile 113 veri kaybı doğurur. Maliyet eğrisi düzleşirken yeniden kurma eğrisi dikleşir.
Sınırın görülmeyen bir yararı da vardır. Ömür sınırı yokken 3 talep hiç karşılanamaz, çünkü unutulan ortamlar havuzu doldurur; sınır konduğu anda teslimsiz talep sıfırlanır. Kullanılmayan ortamın maliyeti yalnız hesapta değil, başka ekiplerin beklemesinde ödenir.
Gizlenen Katmanın Bedeli
| Ölçü | Talep kuyruğu | İstek üzerine | Altın yol dışında |
|---|---|---|---|
| ortalama bekleme | 83,2 saat | 10,1 saat | 6,0 saat |
| teslim / teslimsiz | 83 / 7 | 60 / 3 | 27 / 0 |
| ortam-gün | 3.528 | 877 | 1.212 |
| boşta ortam-günü | 3.133 (%89) | 580 (%66) | 1.090 (%90) |
| unutulan ortam | 73 | 12 | 22 |
| ortam başına insan emeği | 6 saat | 0 saat | 6 saat |
Gizlenen katman ortamın kurulum adımlarıdır ve kazanç 336 insan-saattir: kuyruk yolunda 498 saat harcanan iş, platform yolunda 162 saate iner. Eşik de aynı hesaptan çıkar. Platformun bir çeyrekteki bedeli 344 insan-saat, beş ekibin toplam kazancı 378 insan-saattir; eşik ancak beşinci ekipte aşılır ve o eşiği aşan ekip yıllık talebi en düşük olan raporlama ekibidir. Üç ekiple aynı platform kendini ödemez. Sayı tek yöne bakmaz: aynı model, az sayıda ekibin çalıştığı bir ağda platformun kurulmaması gerektiğini de söyler.
Soyutlama iki noktada sızar. Birincisi havuzdur: 90 günün 16’sında havuz doludur ve o günlerde bekleme kuyruk yolundaki gibi geri gelir — ekip istediği anda ortam alacağını sanır, gerçekte alt katmanın kapasitesine çarpar. İkincisi ömür sınırıdır: ortamın kalıcı olmadığı bilgisi ekibe ancak veri kaybı olayında görünür, ve o bilgi belge okuyarak değil, çalışma kaybederek öğrenilir.
Dışına çıkanlar tek bir gerekçeyle çıkar. Alan donanımlı ortam isteyen 27 talebin tamamı saha ekibindendir ve bu ekip platform hizmetinin hiçbirinden yararlanmaz: ortamını kendi kurar, ömür sınırı işlemez, ortam-gününün yüzde 90’ı boşta durur ve 22 ortamı unutulur. Kısmi yararlanma yoktur; bir talebin biçimi sunulan iki biçime oturmuyorsa o talep bütün yaşam döngüsünü platformun dışında geçirir.
Özet
- Aynı 90 talep kuyruk yolunda ortalama 83,2 saat, istek üzerine yolda 10,1 saat bekledi; kuyruk yolunda 7 talep pencere kapanana kadar hiç karşılanmadı.
- Bekleme boşta duran kaynağı üretti: kuyruk yolunda 3.528 ortam-gününün %89’u kullanılmadı ve 83 ortamın 73’ü unutulan ortama dönüştü.
- Ömür sınırı 14 güne çekilince maliyet 877 ortam-gününden 425’e indi ve hiç yeniden kurma doğmadı; 1 güne çekilince maliyet yalnız 314’e indi ama 251 yeniden kurma ve 113 veri kaybı olayı çıktı.
- Ömür sınırı havuzu da boşalttı: sınırsız yolda karşılanamayan 3 talep, sınır konduğunda sıfırlandı.
- Platformun çeyreklik bedeli 344 insan-saat, beş ekibin kazancı 378 insan-saat; eşik ancak beşinci ekipte aşıldı ve saha ekibi bu kazanca hiç katkı vermedi.
- Soyutlama iki yerden sızdı: 90 günün 16’sında havuz doldu ve bekleme geri geldi; ömür sınırının varlığı ekibe ancak veri kaybıyla göründü.
Sonraki Adım
Ortam artık istendiği anda var oluyor, ama içine konacak şey hâlâ elle yazılıyor. Ölçüm ağına altıncı bir servis eklenmesi gerektiğinde ekip boş bir dizinle başlıyor ve kütük biçiminden sağlık ucuna, derleme adımından ölçüt yayınına kadar her kararı yeniden veriyor — üstelik beş ekip bu kararları birbirinden habersiz veriyor. Bir sonraki ders yeni servis başlatma akışını ele alır: gerçek dosyalar üretilir, elle yazılanla üretilen karşılaştırılır, ve üretimden sonra şablon güncellendiğinde kaç servisin geride kaldığı sayılır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.