Ders 02 / 21
Sürekli Teslimat ve Sürekli Dağıtım
Aynı hattın iki kipte koşturulması: her yeşil koşum yayına hazır (teslimat) ile her yeşil koşum yayında (dağıtım) arasındaki fark üretime giden değişiklik, karar veren insan sayısı, bekleme süresi ve elle onayın yakaladığı gerçek kusurla ölçülür; onayın marjinal değeri yığın büyüklüğüne bağlanır.
İçindekiler
Önceki ders ana dala giriş kapısını ölçtü ve tek soruya cevap verdi: bu değişiklik girsin mi? Yeşil bir ana dalın ardından ne olacağı sorusuna dokunmadı. İki cevap vardır ve aradaki fark tek bir kapıdadır.
Sürekli teslimat (continuous delivery), her yeşil koşumun yayına hazır bir çıktı üretmesidir: çıktı paketlenmiş, sınanmış ve üretime konabilir durumdadır, ama konması bir insan kararına bağlıdır. Sürekli dağıtım (continuous deployment), her yeşil koşumun yayında olmasıdır: kapıların hepsi otomatiktir, aralarında insan yoktur. İkisi arasındaki tek yapısal fark, hattın sonundaki elle onay kapısıdır. Bu ders o kapıyı ölçer: kaç gerçek kusur tutuyor, tuttuklarının kaçını otomatik kapılar zaten görüyordu, kaç temiz değişikliği boşuna durduruyor ve ne kadar bekletiyor.
Akış ve Kusur Sınıfları
Ölçüm bölgesel ölçüm ağının hattı üzerinde yapılır: sayaç okuma toplayıcı, doğrulayıcı, faturalama ve iş emri servisleri. Ağ da hat da kurgudur; aşağıdaki akış bir modeldir. Süreler model dakikasıdır.
HT7 — yirmi iş gününde 320 değişiklik ana dala girer, otuz dakikada bir. Bu sıklık önceki dersin en düşük toplamı verdiği dört saatlik aralıktan gelir: sekiz geliştirici, dörder saatte bir. Yedi kusur sınıfının yüz değişiklikteki sayıları ve dört olasılığı aşağıdadır — otomatik kapının durdurma olasılığı, gecelik takımın bir koşumda yakalama olasılığı, onaylayanın küçük yığında görme olasılığı ve otomatik kapının durdurmadan uyarı üretme olasılığı.
HT8 — hattın kendi süresi değişiklik başına 26 model dakikasıdır.
HT9 — onaylayan altı değişikliği tam görür; yığın bundan büyükse dikkat 6/n oranında seyrelir. Onay bir yığını inceler, tek tek değişiklikleri değil. İncelemenin süresi 15 + 4n model dakikasıdır ve kararı iki kişi verir: onaylayan ile yayın sahibi.
HT10 — temiz bir yığının boşuna geri çevrilme olasılığı 0,08’dir. Uyarıyı sert kapıya çeviren kipte temiz bir değişikliğin boş uyarı üretme olasılığı 0,06’dır.
HT11 — üretime kaçan bir kusurun teşhisi 30 + 12×(yığın−1) model dakikasıdır. Yığın büyüdükçe şüpheli değişiklik sayısı artar ve kusuru hangisinin getirdiği aranır.
HT12 — gecelik takım her gün sonunda bir kez koşar. Bekleme süresine sığan her koşum, sınıfın gecelik olasılığıyla bağımsız bir çekiliş yapar.
// akis.mjs — degisiklik akisi ve kusur siniflari; ayni cekilisler her kipte kullanilir const uretec = (tohum) => () => { tohum = (tohum * 1664525 + 1013904223) >>> 0; return tohum / 4294967296; }; // HT7: yuz degisiklikte ortaya cikma sayisi. kapi = her kosumda calisan otomatik kapilarin // kirmiziya dondurme olasiligi, gecelik = gecelik takimin bir kosumda yakalama olasiligi, // elle = onaylayanin kucuk yiginda gorme olasiligi, uyari = otomatik kapilarin durdurmadan // uyari uretme olasiligi. export const siniflar = [ { ad: 'birim kapsami disi kosul', sayi: 9, kapi: 0.90, gecelik: 0.50, elle: 0.05, uyari: 0.30 }, { ad: 'sema uyusmazligi', sayi: 6, kapi: 0.75, gecelik: 0.60, elle: 0.10, uyari: 0.40 }, { ad: 'yapilandirma kaymasi', sayi: 5, kapi: 0.15, gecelik: 0.35, elle: 0.60, uyari: 0.55 }, { ad: 'goc ile yayin sirasi', sayi: 4, kapi: 0.10, gecelik: 0.20, elle: 0.75, uyari: 0.45 }, { ad: 'is kurali yanlisligi', sayi: 4, kapi: 0.20, gecelik: 0.15, elle: 0.30, uyari: 0.10 }, { ad: 'esik degeri', sayi: 3, kapi: 0.10, gecelik: 0.30, elle: 0.12, uyari: 0.35 }, { ad: 'es zamanlilik yarisi', sayi: 3, kapi: 0.05, gecelik: 0.10, elle: 0.00, uyari: 0.05 }, ]; export const DEGISIKLIK = 320, ARA = 30; // HT7: yirmi is gunu, 30 dakikada bir birlestirme export const GUN_DK = 480, HAFTA_DK = 2400; // Her degisikligin butun cekilisleri onceden uretilir: kipler ayni sayilarla karsilastirilir. export const akisUret = (tohum) => { const r = uretec(tohum); return Array.from({ length: DEGISIKLIK }, (_, i) => { let x = r() * 100, sinif = null; for (const s of siniflar) { x -= s.sayi; if (x <= 0) { sinif = s; break; } } return { t: i * ARA, sinif, kapiCekilis: r(), elleCekilis: r(), uyariCekilis: r(), yanlisCekilis: r(), gecelikCekilis: Array.from({ length: 8 }, () => r()) }; }); };
Altı Kip
Karşılaştırılan altı kip iki ekseni ayırır: yayın penceresi (bekleme) ve onay (insan). Üçüncü satır bu ayrımın anahtarıdır — günlük pencere vardır ama onay yoktur, yani beklemenin kendi kazancı insanınkinden ayrı ölçülür.
// kip.mjs — ayni hat alti kipte: her yesil kosum yayinda (dagitim) ya da yayina hazir (teslimat) import { akisUret, DEGISIKLIK, GUN_DK, HAFTA_DK } from './akis.mjs'; const HAT_DK = 26; // HT8: hattin kendi suresi const DIKKAT = 6; // HT9: tam gorulen yigin buyuklugu const ONAY_TABAN = 15, ONAY_BIRIM = 4, ONAY_KISI = 2; // HT9: onay suresi ve karar veren kisi const YANLIS_RET = 0.08, BOS_UYARI = 0.06; // HT10: bosuna durdurma olasiliklari const TESHIS_TABAN = 30, TESHIS_BIRIM = 12; // HT11: uretimdeki kusurun teshis suresi const kipler = [ { ad: 'dagitim', pencere: 0, onay: false }, { ad: 'teslimat, her kosum', pencere: 0, onay: true }, { ad: 'gunluk pencere, onaysiz', pencere: GUN_DK, onay: false }, { ad: 'teslimat, gunluk onay', pencere: GUN_DK, onay: true }, { ad: 'teslimat, haftalik onay', pencere: HAFTA_DK, onay: true }, { ad: 'dagitim, uyari sert kapi', pencere: 0, onay: false, sert: true }, ]; const olc = (kip, akis) => { const yigin = new Map(); let sertTuttu = 0, yanlis = 0; for (const d of akis) { if (d.sinif && d.kapiCekilis < d.sinif.kapi) continue; // otomatik kapi kirmiziya dondurdu let ek = 0; if (kip.sert) { if (d.sinif && d.uyariCekilis < d.sinif.uyari) { sertTuttu++; continue; } if (!d.sinif && d.yanlisCekilis < BOS_UYARI) { yanlis++; ek = HAT_DK; } } const hazir = d.t + HAT_DK + ek; const yayin = kip.pencere === 0 ? hazir : Math.ceil(hazir / kip.pencere) * kip.pencere; (yigin.get(yayin) ?? yigin.set(yayin, []).get(yayin)).push({ d, hazir }); } let giden = 0, karar = 0, bekleme = 0, enKotu = 0, tuttu = 0, uyarili = 0; let onayDk = 0, kacan = 0, teshisDk = 0, yiginToplam = 0, yayinSayisi = 0; for (const [yayin, kayitlar] of [...yigin.entries()].sort((a, b) => a[0] - b[0])) { const n = kayitlar.length; yayinSayisi++; yiginToplam += n; const dikkat = Math.min(1, DIKKAT / n); // HT9: yigin buyudukce seyrelir let ret = false; if (kip.onay) { karar += ONAY_KISI; onayDk += (ONAY_TABAN + ONAY_BIRIM * n) * ONAY_KISI; } for (const { d, hazir } of kayitlar) { // HT12: bekleme sirasinda kac gecelik kosum sigiyor const kosum = Math.floor(yayin / GUN_DK) - Math.floor(hazir / GUN_DK); let durdu = false; if (d.sinif) { for (let k = 0; k < Math.min(kosum, 8); k++) { if (d.gecelikCekilis[k] < d.sinif.gecelik) { durdu = true; break; } } if (!durdu && kip.onay && d.elleCekilis < d.sinif.elle * dikkat) { durdu = true; ret = true; tuttu++; if (d.uyariCekilis < d.sinif.uyari) uyarili++; // otomatik kapi zaten uyarmisti } } if (durdu) continue; if (d.sinif) { kacan++; teshisDk += TESHIS_TABAN + TESHIS_BIRIM * (n - 1); } giden++; bekleme += yayin - hazir; enKotu = Math.max(enKotu, yayin - hazir); } if (kip.onay && !ret && kayitlar[0].d.yanlisCekilis < YANLIS_RET) yanlis += n; } return { yayinSayisi, yigin: yiginToplam / yayinSayisi, giden, karar, bekleme: bekleme / giden, enKotu, tuttu, uyarili, yanlis, onayDk, kacan, teshisDk, sertTuttu }; }; const akis = akisUret(51301); const sonuc = kipler.map((k) => ({ ad: k.ad, r: olc(k, akis) })); const bul = (ad) => sonuc.find((x) => x.ad === ad).r; const s = (x, w) => String(x).padStart(w); const f = (x, w) => String(x.toFixed(1)).padStart(w); console.log(`degisiklik ${DEGISIKLIK}, kusur tasiyan ${akis.filter((d) => d.sinif).length}\n`); console.log(`${'kip'.padEnd(25)}${s('yayin', 7)}${s('ort yigin', 11)}${s('uretime giden', 15)}${s('insan karari', 14)}${s('ort bekleme', 13)}${s('en kotu', 9)}`); for (const { ad, r } of sonuc) { console.log(`${ad.padEnd(25)}${s(r.yayinSayisi, 7)}${f(r.yigin, 11)}${s(r.giden, 15)}` + `${s(r.karar, 14)}${f(r.bekleme, 13)}${s(r.enKotu, 9)}`); } console.log(`\n${'kip'.padEnd(25)}${s('onay tuttu', 12)}${s('zaten uyarili', 15)}${s('uretime kacan', 15)}${s('yanlis tuttu', 14)}${s('insan dk', 10)}${s('teshis dk', 11)}`); for (const { ad, r } of sonuc) { console.log(`${ad.padEnd(25)}${s(r.tuttu, 12)}${s(r.uyarili, 15)}${s(r.kacan, 15)}` + `${s(r.yanlis, 14)}${s(r.onayDk, 10)}${s(r.teshisDk, 11)}`); } const sert = bul('dagitim, uyari sert kapi'); const ozet = (tohum) => { const a = akisUret(tohum), h = (ad) => olc(kipler.find((k) => k.ad === ad), a); return { tek: h('dagitim').kacan - h('teslimat, her kosum').kacan, gun: h('gunluk pencere, onaysiz').kacan - h('teslimat, gunluk onay').kacan, sert: h('dagitim, uyari sert kapi').kacan, cip: h('dagitim').kacan }; }; console.log(`\nonayin marjinali: pencere yokken ${bul('dagitim').kacan - bul('teslimat, her kosum').kacan} kusur, ` + `gunluk pencerede ${bul('gunluk pencere, onaysiz').kacan - bul('teslimat, gunluk onay').kacan} kusur`); console.log(`gunluk pencerenin onaysiz kazanci ${bul('dagitim').kacan - bul('gunluk pencere, onaysiz').kacan} kusur, insan dakikasi 0`); console.log(`sert kapi ${sert.sertTuttu} degisikligi durdurdu, ${sert.yanlis} tanesi bosunaydi; uretime kacan ${sert.kacan}`); console.log('tohum taramasi (onay marjinali tek/gunluk, sert kapi kacan, onaysiz dagitim kacan):'); for (const tohum of [51301, 8802, 33107, 6449]) { const o = ozet(tohum); console.log(` ${tohum}: ${o.tek}/${o.gun}, ${o.sert}, ${o.cip}`); }
degisiklik 320, kusur tasiyan 116 kip yayin ort yigin uretime giden insan karari ort bekleme en kotu dagitim 264 1.0 264 0 0.0 0 teslimat, her kosum 264 1.0 242 528 0.0 0 gunluk pencere, onaysiz 20 13.2 247 0 224.8 454 teslimat, gunluk onay 20 13.2 242 40 226.5 454 teslimat, haftalik onay 4 66.0 239 8 1152.0 2374 dagitim, uyari sert kapi 236 1.0 236 0 0.0 0 kip onay tuttu zaten uyarili uretime kacan yanlis tuttu insan dk teshis dk dagitim 0 0 60 0 0 1800 teslimat, her kosum 22 14 38 16 10032 1140 gunluk pencere, onaysiz 0 0 43 0 0 7890 teslimat, gunluk onay 5 3 38 26 2712 6972 teslimat, haftalik onay 2 2 35 0 2232 28662 dagitim, uyari sert kapi 0 0 32 3 0 960 onayin marjinali: pencere yokken 22 kusur, gunluk pencerede 5 kusur gunluk pencerenin onaysiz kazanci 17 kusur, insan dakikasi 0 sert kapi 28 degisikligi durdurdu, 3 tanesi bosunaydi; uretime kacan 32 tohum taramasi (onay marjinali tek/gunluk, sert kapi kacan, onaysiz dagitim kacan): 51301: 22/5, 32, 60 8802: 20/6, 45, 60 33107: 14/6, 50, 64 6449: 21/6, 48, 69
Beklemenin Kazancı Kimin
Birinci tablo iki kipin akış farkını verir. Dağıtım kipinde yirmi iş gününde 264 yayın olur, üretime giden değişiklik 264’tür ve hiç insan kararı yoktur. Haftalık onaylı teslimatta yayın sayısı dörttür, yığın ortalama 66 değişikliktir, insan kararı sekizdir ve hazır olup yayınlanmayan bir değişiklik ortalama 1152, en kötü durumda 2374 model dakikası bekler — yaklaşık beş iş günü. Aynı hat, aynı çıktı, aynı sınamalar; fark yalnız sondaki kapıdadır.
İkinci tablonun uretime kacan sütunu ilk bakışta beklemeyi haklı çıkarır: dağıtımda 60,
haftalıkta 35. Kritik satır üçüncüdür. Günlük pencere, onaysız kipi kaçan kusuru 60’tan
43’e indirir ve bunu sıfır insan dakikasıyla yapar. Bu 17 kusuru insan bulmamıştır; bekleme
süresine sığan gecelik koşumlar bulmuştur. Elle onayın hanesine yazılan iyileşmenin büyük
kısmı, aslında makineye tanınan ek zamanın kazancıdır — ve o zaman insansız da tanınabilir.
Beklemenin faturası ise teshis dk sütunundadır. Dağıtımda 60 kusurun teşhisi 1800 dakika,
kusur başına 30 dakikadır: yayında tek değişiklik vardır, şüpheli bellidir. Haftalık kipte 35
kusurun teşhisi 28 662 dakika, kusur başına 819 dakikadır — yirmi yedi kat. Yığın büyüdükçe
üretimdeki her arıza için 66 aday arasından seçim yapmak gerekir. Bekleme kaçan kusuru
azaltır, kaçanın bedelini büyütür.
Elle Onayın Marjinal Değeri
Onay kapısının marjinali, aynı çekilişlerle onaylı ve onaysız koşumun kaçan kusur farkıdır. Yığın bir değişiklikken bu fark 22 kusurdur — onay ciddi bir kapıdır. Günlük pencerede aynı fark 5 kusura düşer. Kapının kendisi değişmemiştir; değişen, incelediği yığındır. Onay kapısı kendi beklemesini üretir, bekleme yığını büyütür, yığın dikkati seyreltir: 13,2 değişikliklik bir yığında dikkat 6/13,2, yani 0,45’tir. Kapı kendi varlığıyla kendi etkisini yüzde 77 azaltır. Haftalık pencerede 66’lık yığında marjinal 2 kusurdur.
İkinci sayı daha da keskindir. zaten uyarili sütunu, onayın tuttuğu kusurlardan kaçı için
otomatik kapıların hâlihazırda bir uyarı ürettiğini sayar: yığın bir iken 22’nin 14’ü, günlük
pencerede 5’in 3’ü. Bu kusurlar için insan, makinenin zaten yazdığı satırı okumuştur. Uyarı
sert kapıya çevrilseydi onay olmadan da durdurulacaklardı. Onayın yalnız kendisine ait
katkısı iki durumda 8 ve 2 kusurdur.
Son satır bu düşünceyi sonuna götürür. Uyarıların sert kapıya çevrildiği dağıtım kipinde 28 değişiklik durdurulur, üçü boşuna; kaçan kusur 32’ye iner. Bu, bekleme ve onay içeren her kipten daha iyidir: sıfır insan dakikası, sıfır bekleme, kusur başına 30 dakikalık teşhis. Tohum taraması sayının oynadığını gösterir — sert kapıda kaçan 32 ile 50 arasında, onaysız dağıtımda 60 ile 69 arasında değişir — ama sıralama dört tohumda da aynıdır.
Elle onay kapısının üç sayısı böylece yazılabilir. Tuttuğu: günlük pencerede 5 kusur, yalnız kendisinin tuttuğu 2. Kaçırdığı ve yanlış tuttuğu: 38 kusur üretime gider, 26 temiz değişiklik boşuna durdurulur. Eklediği süre: 2712 insan dakikası ve değişiklik başına 226,5 dakika bekleme. Bu üç satır yan yana yazıldığında kapı savunulamaz hâle gelir; tek başına “onaylayan biri olsun” cümlesi ise hiçbir sayı taşımaz.
Özet
- Sürekli teslimat ile sürekli dağıtım arasındaki tek yapısal fark, yeşil koşum ile üretim arasında duran elle onay kapısıdır; ölçüm bu kapıya yapıldı.
- Elle onayın marjinali yığına bağlıdır: yığın bir değişiklikken 22 kusur, günlük pencerede 5, haftalık pencerede 2. Kapı kendi beklemesini üretip kendi etkisini yüzde 77 azaltır.
- Onayın tuttuğu kusurların çoğu için otomatik kapılar zaten uyarı üretmişti (22’nin 14’ü, 5’in 3’ü); onaya ait eşsiz katkı 8 ve 2 kusurdur.
- Beklemenin kazancı insanın değil makinenindir: günlük pencere onaysız hâlde kaçan kusuru 60’tan 43’e indirdi, insan dakikası sıfırdı.
- Bekleme kaçanın bedelini büyütür: teşhis kusur başına 30 dakikadan 819 dakikaya çıktı, çünkü 66’lık yığında şüpheli sayısı 66’dır.
- Uyarıyı sert kapıya çeviren onaysız dağıtım kaçanı 32’ye indirdi; sıfır insan dakikası ve sıfır beklemeyle her onaylı kipten iyi sonuç verdi.
Sonraki Adım
Bu dersin ölçtüğü kapı hattın sonundaydı ve ondan önceki her şey tek bir kutu olarak, “otomatik kapılar” adıyla anıldı. O kutunun içinde birden çok kapı vardır: derleme, test, paketleme ve yayın. Sondaki onayın marjinali hesaplanabildiğine göre içerideki her kapının marjinali de hesaplanabilir — hangi kusuru yalnız o kapı tutuyor, hangisini kaçırıyor, kaç temiz değişikliği boşuna durduruyor ve hatta kaç dakika ekliyor. Sonraki ders bilinen bir kusur kümesini bir hat modelinden geçirir, her kusurun hangi kapıda yakalandığını izler ve kapılardan birinin kaldırılmasını dener.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.