Ders 01 / 12
DevOps Nedir
Sorumluluk paylaşımının teknik ve örgütsel yanı: aynı 22 olgunun ayrık gözlem alanlarında 9'unun yalnız işletenin, 1'inin yalnız yazanın alanında ve 1'inin hiçbir alanda görünmesi, 4 olgunun sahibine hiç ulaşmaması ve sahibe ulaşmanın ortalama 7,0 adım sürmesi, üç yüzeyin paylaşılmasıyla ulaşmayanın 1'e ve ulaşmanın 5,0 adıma inmesi, alanların tümüyle birleştirilmesiyle ulaşmanın 1,6 adıma inerken yazan ekibin yükünün 95'ten 107 adıma, öncü sürenin 25,8'den 34,8 adıma çıkması ve dağıtım sıklığının 5'ten 4 yayına düşmesi.
İçindekiler
Önceki ders devri bir sözleşme olarak ölçtü: yirmi sekiz sorumluluk kaleminin yirmisi devredildi, sekizi bilgi, araç ya da yordam yokluğunda geliştirmede kaldı. Sözleşme kimin neyi yapacağını yazıyordu. Yazmadığı şey, kimin neyi göreceğiydi. İki taraf aynı servisten sorumlu olabilir ve yine de aynı olguyu farklı adımda, farklı yüzeyde, kimi zaman hiç görmez.
Sorumluluk paylaşımı, yazan ve işleten rollerin bir servisin sonucundan birlikte sorumlu tutulmasıdır. Devir sözleşmesi kalemleri böler, sorumluluk paylaşımı sonucu böler; ikincisinin ön koşulu, iki tarafın aynı olguyu görebilmesidir. Bu ders o ön koşulu ölçer: aynı olgu kümesi iki rolün gözlem alanına düşürülür, kaç olgunun yalnız bir tarafta kaldığı sayılır ve alanları birleştirmenin faturası çıkarılır.
Gözlem Alanı Bir Veri Yapısıdır
Örnek, bu müfredatın kurgu bölgesel ölçüm ağıdır: bir belediyenin su sayaçlarından okuma
toplayan, okumaları doğrulayan, faturaya çeviren ve saha ekiplerine iş emri açan bir yazılım. Ağ
da ekipler de kurgudur. KA1: üç ortam (geliştirme, sınama, üretim), iki ekip (yazan ve
işleten) ve bir gecelik toplu iş vardır. KA2: sekiz gözlem yüzeyi vardır; üçü yazan ekibin,
dördü işleten ekibin alanındadır, fatura-dokumu hiç kimsenin alanında değildir. KA3: bir
pencerede yirmi iki olgu doğar; her olgunun bir sınıfı (hata, gecikme, sapma), bir doğuş adımı ve
göründüğü yüzeylerle o yüzeydeki gecikmesi vardır. KA4: her olgunun onu kapatabilen bir sahibi
vardır — yazan, işleten ya da ortak; ortak olgu iki alanda da görünmedikçe kapatılamaz, kapatma
sırasıyla 4, 2 ve 5 adım tutar. KA5: alanında görünen olgu role 2 adım inceleme yazar; sahibine
30 adımda ulaşmamış olgu üstten duyulur ve bağlam ikinci elden kurulduğu için 2 adım fazladan
tutar. KA6: yazan ekip boş adımlarında yayına çalışır, bir yayın 8 adım iş ister; her olgu
kendinden önceki son yayına bağlanır ve bağlı olgusu sahibine hiç ulaşmayan yayın başarısız
sayılır. Pencere 140 adımdır.
Olgular, yüzeyler ve iki rolün nöbeti süreç içi bir modeldir; gerçek bir uyarı akışı ya da olay kaydı yoktur.
// gozlem/alan.mjs — kurgu bolgesel olcum aginin olgu ve gozlem alani modeli (model): gercek bir // uyari akisi ya da olay kaydi yok, adimlar veri yapisidir. Rastgelelik yok. export const PENCERE = 140; // olculen adim penceresi export const INCELEME = 2; // bir olgunun bir role inceleme maliyeti (adim) export const YAYIN_ISI = 8; // bir yayin icin gereken calisma adimi export const KAPATMA = { yazan: 4, isleten: 2, ortak: 5 }; export const TAVAN = 30; // sahibine ulasmayan olgu bu gecikmeyle ustten duyulur export const IKINCI_EL = 2; // ustten duyulan olgunun ek baglam maliyeti export const YUZEY = { // yuzey -> ayrik duzende kimin alaninda "uygulama-kaydi": "yazan", "hata-izleme": "yazan", "surum-gunlugu": "yazan", "is-cizelgesi": "isleten", "makine-olcumu": "isleten", "uyari-akisi": "isleten", "destek-kaydi": "isleten", "fatura-dokumu": "-", }; export const ROL = ["yazan", "isleten"]; const cizelge = (s, f) => s.trim().split("\n").map((r) => f(r.trim().split(/\s+/))); // olgu: dogus adimi, sinif, kapatabilen rol, ad, gorundugu yuzeyler (yuzey:gecikme) export const OLGU = cizelge(` 2 hata yazan okuma-ayristirici uygulama-kaydi:0 destek-kaydi:12 6 gecikme isleten toplu-is-tasmasi is-cizelgesi:1 makine-olcumu:2 11 sapma yazan sinamada-olmayan-ayar surum-gunlugu:0 uyari-akisi:9 17 hata isleten kuyruk-tikanmasi makine-olcumu:0 uyari-akisi:1 21 gecikme yazan sorgu-yavaslamasi uygulama-kaydi:3 makine-olcumu:1 26 hata yazan yinelenen-fatura destek-kaydi:16 31 sapma isleten disk-doluluk makine-olcumu:0 36 hata yazan bos-adresli-is-emri hata-izleme:2 destek-kaydi:9 42 gecikme isleten ag-gecikmesi makine-olcumu:1 uyari-akisi:2 46 sapma yazan kutuphane-sapmasi surum-gunlugu:1 51 hata ortak gecelik-is-yarim is-cizelgesi:1 uygulama-kaydi:4 57 hata yazan negatif-tuketim fatura-dokumu:0 destek-kaydi:14 61 gecikme isleten yedekleme-cakismasi is-cizelgesi:2 makine-olcumu:3 66 sapma ortak zaman-dilimi-farki uygulama-kaydi:6 is-cizelgesi:3 71 hata yazan yuvarlama-farki fatura-dokumu:0 77 gecikme yazan onbellek-isinmasi hata-izleme:2 makine-olcumu:1 81 hata isleten baglanti-havuzu uyari-akisi:1 uygulama-kaydi:0 86 sapma yazan eksik-ortam-degiskeni uygulama-kaydi:0 uyari-akisi:5 91 hata yazan sayac-kimligi-catismasi hata-izleme:2 destek-kaydi:10 96 gecikme isleten is-yeniden-kosumu is-cizelgesi:1 102 sapma yazan bicim-kirilmasi fatura-dokumu:0 destek-kaydi:15 107 hata ortak yinelenen-is-emri uygulama-kaydi:3 destek-kaydi:8`, ([dogus, sinif, sahip, ad, ...y]) => ({ dogus: +dogus, sinif, sahip, ad, yuzey: y.map((p) => ({ ad: p.split(":")[0], gec: +p.split(":")[1] })) })); // Duzen: ayrik duzenin uzerine hangi rol hangi yuzeyi ek olarak goruyor (karsit kosum). export const DUZEN = { ayrik: { yazan: [], isleten: [] }, secili: { yazan: ["destek-kaydi"], isleten: ["surum-gunlugu", "fatura-dokumu"] }, birlesik: { yazan: Object.keys(YUZEY), isleten: Object.keys(YUZEY) }, }; export const alan = (d) => Object.fromEntries(ROL.map((r) => [r, new Set([...Object.keys(YUZEY).filter((y) => YUZEY[y] === r), ...DUZEN[d][r]])])); export function kos(d) { const A = alan(d); const G = OLGU.map((o) => { // her olgu her rolde kacinci adimda goruluyor const g = Object.fromEntries(ROL.map((r) => { const v = o.yuzey.filter((y) => A[r].has(y.ad)).map((y) => y.gec); return [r, v.length ? Math.min(...v) : null]; })); const kapi = o.sahip === "ortak" // ortak olgu iki alanda da gorunmus olmali ? (g.yazan === null || g.isleten === null ? null : Math.max(g.yazan, g.isleten)) : g[o.sahip]; return { o, g, kapi, sahipRol: o.sahip === "ortak" ? "yazan" : o.sahip }; }); const kuyruk = Object.fromEntries(ROL.map((r) => [r, []])); const kalan = Object.fromEntries(ROL.map((r) => [r, 0])); const yuk = Object.fromEntries(ROL.map((r) => [r, 0])); const kapanis = new Map(), yayin = []; let birikim = 0, basla = 0; for (let t = 0; t <= PENCERE; t++) { for (const x of G) { for (const r of ROL) // alaninda gorunen olgu inceleme isi acar if (x.g[r] !== null && t === x.o.dogus + x.g[r]) kuyruk[r].push([INCELEME, null]); if (x.kapi !== null && t === x.o.dogus + x.kapi) kuyruk[x.sahipRol].push([KAPATMA[x.o.sahip], x]); else if (x.kapi === null && t === x.o.dogus + TAVAN) // ustten duyulma kuyruk[x.sahipRol].push([KAPATMA[x.o.sahip] + IKINCI_EL, x]); } for (const r of ROL) { if (kalan[r] === 0 && kuyruk[r].length) [kalan[r]] = kuyruk[r][0]; if (kalan[r] > 0) { // rol bu adimda olguyla ugrasiyor kalan[r]--; yuk[r]++; if (kalan[r] === 0) { const [, x] = kuyruk[r].shift(); if (x) kapanis.set(x.o.ad, t + 1); } continue; } if (r !== "yazan") continue; // bos adim: yazan ekip yayina calisir if (birikim === 0) basla = t; if (++birikim === YAYIN_ISI) { yayin.push({ t: t + 1, basla, olgu: [] }); birikim = 0; } } } for (const x of G) { // olgu kendinden onceki son yayina baglanir const y = [...yayin].reverse().find((v) => v.t <= x.o.dogus); if (y) y.olgu.push(x); } return { G, yuk, kapanis, yayin }; } export const ort = (a) => (a.length ? (a.reduce((s, v) => s + v, 0) / a.length).toFixed(1) : "-"); export function olc(d) { const R = kos(d), say = (f) => R.G.filter(f).length; const ulasma = R.G.map((x) => (x.kapi === null ? TAVAN : x.kapi)); // ulasmayana tavan yazilir const sure = R.G.map((x) => (R.kapanis.get(x.o.ad) ?? PENCERE) - x.o.dogus); const bozuk = R.yayin.filter((y) => y.olgu.some((x) => x.kapi === null)).length; return { R, yalnizYazan: say((x) => x.g.yazan !== null && x.g.isleten === null), yalnizIsleten: say((x) => x.g.isleten !== null && x.g.yazan === null), ikisi: say((x) => x.g.yazan !== null && x.g.isleten !== null), hicbiri: say((x) => x.g.yazan === null && x.g.isleten === null), ulasmayan: say((x) => x.kapi === null), ulasmaAdimi: ort(ulasma), gurultuYazan: say((x) => x.g.yazan !== null && x.o.sahip === "isleten"), gurultuIsleten: say((x) => x.g.isleten !== null && x.o.sahip === "yazan"), yukYazan: R.yuk.yazan, yukIsleten: R.yuk.isleten, kurtarma: ort(sure), yayinSayisi: R.yayin.length, onculSure: ort(R.yayin.map((y) => y.t - y.basla)), geriDonus: R.yayin.length ? (100 * bozuk / R.yayin.length).toFixed(0) + "%" : "-" }; }
Dört teslimat ölçütü aynı koşumdan okunur: dağıtım sıklığı penceredeki yayın sayısı, öncü süre bir yayının işine başlanmasından yayına girmesine kadar geçen adım, geri dönüş oranı başarısız yayınların payı, kurtarma süresi olgunun doğuşundan kapanışına kadar geçen adımdır.
// gozlem/olc.mjs — olgu iki rolun gozlem alanina nasil dusuyor, birlestirmenin bedeli ne. import { OLGU, YUZEY, ROL, olc, alan, TAVAN } from "./alan.mjs"; const yaz = (g, ...s) => console.log(s.map((v, i) => (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join("")); const D = ["ayrik", "secili", "birlesik"]; const R = Object.fromEntries(D.map((d) => [d, olc(d)])); console.log(`${OLGU.length} olgu, ${Object.keys(YUZEY).length} gozlem yuzeyi; ` + ["hata", "gecikme", "sapma"].map((s) => `${s} ${OLGU.filter((o) => o.sinif === s).length}`).join(", ")); for (const r of ROL) console.log(` ${r}: ${[...alan("ayrik")[r]].join(", ")}`); console.log(` kimsenin alaninda degil: ` + Object.keys(YUZEY).filter((y) => YUZEY[y] === "-").join(", ")); const A = [-27, 9, 9, 11]; console.log("\n1. ayni 22 olgu, uc gozlem duzeni"); yaz(A, "olcu", "ayrik", "secili", "birlesik"); for (const [ad, k] of [["yalniz yazanin alaninda", "yalnizYazan"], ["yalniz isletenin alaninda", "yalnizIsleten"], ["iki alanda birden", "ikisi"], ["hicbir alanda", "hicbiri"], ["sahibine hic ulasmayan", "ulasmayan"], [`sahibe ulasma (ort. adim)`, "ulasmaAdimi"], ["yazana gurultu (olgu)", "gurultuYazan"], ["isletene gurultu (olgu)", "gurultuIsleten"], ["yazanin yuku (adim)", "yukYazan"], ["isletenin yuku (adim)", "yukIsleten"]]) yaz(A, ad, ...D.map((d) => R[d][k])); console.log("\n2. dort teslimat olcutu, ayni pencerede"); yaz(A, "olcut", "ayrik", "secili", "birlesik"); for (const [ad, k] of [["dagitim sikligi (yayin)", "yayinSayisi"], ["oncu sure (ort. adim)", "onculSure"], ["geri donus orani", "geriDonus"], ["kurtarma suresi (ort. adim)", "kurtarma"]]) yaz(A, ad, ...D.map((d) => R[d][k])); const B = [-9, 7, 16, 18, 18]; console.log("\n3. ayrik duzende olgu sinifi kimin alanina dusuyor"); yaz(B, "sinif", "olgu", "yalniz yazanda", "yalniz isletende", "sahibe ulasmayan"); for (const s of ["hata", "gecikme", "sapma"]) { const g = R.ayrik.R.G.filter((x) => x.o.sinif === s); yaz(B, s, g.length, g.filter((x) => x.g.yazan !== null && x.g.isleten === null).length, g.filter((x) => x.g.isleten !== null && x.g.yazan === null).length, g.filter((x) => x.kapi === null).length); } console.log("\n4. ayrik duzende sahibine ulasmayan olgular (tavan " + TAVAN + " adim)"); const C = [-24, -9, 10, 16]; yaz(C, "olgu", "sahip", "kapanis", "gorundugu alan"); for (const x of R.ayrik.R.G.filter((x) => x.kapi === null)) yaz(C, x.o.ad, x.o.sahip, R.ayrik.R.kapanis.get(x.o.ad) - x.o.dogus, ROL.filter((r) => x.g[r] !== null).join("+") || "hicbiri");
22 olgu, 8 gozlem yuzeyi; hata 10, gecikme 6, sapma 6 yazan: uygulama-kaydi, hata-izleme, surum-gunlugu isleten: is-cizelgesi, makine-olcumu, uyari-akisi, destek-kaydi kimsenin alaninda degil: fatura-dokumu 1. ayni 22 olgu, uc gozlem duzeni olcu ayrik secili birlesik yalniz yazanin alaninda 1 0 0 yalniz isletenin alaninda 9 7 0 iki alanda birden 11 15 22 hicbir alanda 1 0 0 sahibine hic ulasmayan 4 1 0 sahibe ulasma (ort. adim) 7.0 5.0 1.6 yazana gurultu (olgu) 1 1 7 isletene gurultu (olgu) 10 12 12 yazanin yuku (adim) 95 95 107 isletenin yuku (adim) 54 58 58 2. dort teslimat olcutu, ayni pencerede olcut ayrik secili birlesik dagitim sikligi (yayin) 5 5 4 oncu sure (ort. adim) 25.8 27.0 34.8 geri donus orani 40% 20% 0% kurtarma suresi (ort. adim) 13.5 11.9 10.2 3. ayrik duzende olgu sinifi kimin alanina dusuyor sinif olgu yalniz yazanda yalniz isletende sahibe ulasmayan hata 10 0 3 3 gecikme 6 0 4 0 sapma 6 1 2 1 4. ayrik duzende sahibine ulasmayan olgular (tavan 30 adim) olgu sahip kapanis gorundugu alan yinelenen-fatura yazan 42 isleten negatif-tuketim yazan 42 isleten yuvarlama-farki yazan 40 hicbiri bicim-kirilmasi yazan 36 isleten
Sayılar ölçüm sınıfındadır; girdileri yukarıdaki varsayımlardır.
Aynı Olgu, İki Ayrı Alan
Birinci tablonun ayrik sütunu bugünkü bölüşmedir. Yirmi iki olgunun on biri iki alanda birden
görünür, dokuzu yalnız işletenin, biri yalnız yazanın alanındadır, biri de hiçbir alanda
görünmez — fatura-dokumu yüzeyine düşen yuvarlama-farki kimsenin nöbet listesinde yoktur.
Üçüncü tablo bunu sınıfa göre böler: altı gecikmenin dördü yalnız işletenin alanındadır, çünkü
gecikme makine ölçümüne ve iş çizelgesine düşer; altı sapmanın biri yalnız yazanın alanındadır,
çünkü sürüm günlüğünü yalnız yazan ekip okur.
Asıl sayı alt satırdadır: dört olgu sahibine hiç ulaşmaz. Dördüncü tablo bunları adıyla verir ve dördünün de sahibi yazan ekiptir. Üçü işletenin alanında görünür — destek kaydına düşerler, işleten ekip onları görür ama kapatamaz; biri hiçbir yerde görünmez. Üstten duyulmaları 30 adım sürer, kapanışları 36 ile 42 adım arasındadır. Aynı pencerede sahibine ulaşan olguların ortalama ulaşma adımı ile birlikte hesaplandığında sinyalin sahibine ortalama ulaşma süresi 7,0 adımdır.
İşletenin alanındaki on olgu, işletenin kapatamayacağı olgudur; yani ayrık düzende işleten ekip zaten kapatamadığı bir olgu yığınına bakmaktadır. Bölünmüş gözlem alanı sinyali yok etmez, yanlış tarafa koyar.
Alanı Birleştirmenin Faturası
birlesik sütunu iki role sekiz yüzeyin tamamını verir. Görünürlük tamamlanır: yirmi iki olgunun
yirmi ikisi iki alanda birden, sahibine ulaşmayan sıfır, ortalama ulaşma 7,0 adımdan 1,6 adıma
iner. Bedel de aynı sütundadır: yazan ekibe düşen gürültü — kapatamayacağı olgu — 1’den 7’ye,
inceleme yükü 95 adımdan 107 adıma çıkar.
Bu on iki adım ikinci tabloda teslimat ölçütü olarak görünür. Dağıtım sıklığı 5 yayından 4’e iner, öncü süre 25,8 adımdan 34,8 adıma çıkar. Karşılığında geri dönüş oranı %40’tan %0’a, kurtarma süresi 13,5 adımdan 10,2 adıma iner. Dört ölçütün ikisi iyileşir, ikisi bozulur; bir tek ölçüte bakan cümle bu kararı taşıyamaz.
secili sütunu üçüncü seçenektir: sekiz yüzeyden yalnız üçü paylaşılır — yazan ekip destek
kaydını, işleten ekip sürüm günlüğü ile fatura dökümünü görür. Sahibine ulaşmayan olgu 4’ten 1’e,
ortalama ulaşma 7,0’dan 5,0 adıma, geri dönüş oranı %40’tan %20’ye, kurtarma süresi 13,5’ten 11,9
adıma iner. Dağıtım sıklığı 5 yayında kalır ve öncü süre yalnız 1,2 adım artar. Yazan ekibin yükü
hiç değişmez: 95 adımdan 95 adıma. Üç yüzeyin getirdiği inceleme işi, artık üstten duyulmayan
üç olgunun ikinci elden bağlam kurma maliyetini tam olarak karşılar.
Farkın Saklandığı Yer
Bu derste fark gözlem alanının bölünmesinde saklıdır ve sayısı şudur: sekiz yüzeyin dördü tek bir rolde, biri hiçbir roldedir; yirmi iki olgunun onu tek alanda, biri hiçbir alanda görünür. Farkın bildirilmiş kısmı yüzey bölüşmesidir — hangi ekibin neye baktığı bellidir. Bildirilmemiş kısmı, o bölüşmenin hangi olguyu hangi tarafta bıraktığıdır; bu ancak koşumda görünür.
Sinyalin kime kaç adımda ulaştığı da buradan okunur: ayrık düzende sahibine ortalama 7,0 adımda, üç yüzey paylaşıldığında 5,0 adımda, alanlar birleştirildiğinde 1,6 adımda ulaşır. Sorumluluk paylaşımının teknik yanı budur — yüzeylerin kime açıldığı; örgütsel yanı ise açılan yüzeyin getirdiği inceleme yükünün kimin akışından düşüldüğüdür.
Özet
- Yirmi iki olgu ayrık gözlem alanlarında bölünür: 11’i iki alanda, 9’u yalnız işletenin, 1’i yalnız yazanın alanında, 1’i hiçbir alanda görünür; 4 olgu sahibine hiç ulaşmaz ve dördünün de sahibi yazan ekiptir.
- Sinyalin sahibine ulaşması ayrık düzende ortalama 7,0 adım, üç yüzey paylaşıldığında 5,0 adım, alanlar birleştirildiğinde 1,6 adım sürer.
- Birleştirmenin bedeli yazan ekibin akışındadır: gürültü 1’den 7 olguya, yük 95’ten 107 adıma çıkar; dağıtım sıklığı 5’ten 4 yayına iner ve öncü süre 25,8’den 34,8 adıma uzar.
- Karşılığında geri dönüş oranı %40’tan %0’a, kurtarma süresi 13,5’ten 10,2 adıma iner: dört ölçütün ikisi iyileşir, ikisi bozulur.
- Üç yüzeyin seçilerek paylaşılması iyileşmenin çoğunu getirir (ulaşmayan 1, ulaşma 5,0 adım, geri dönüş %20) ve yazan ekibin yükünü 95 adımda sabit bırakır.
Sonraki Adım
Gözlem alanı bölünmüşse sinyal geç ulaşır ya da hiç ulaşmaz; bu ölçüldü. Ama bölünme yalnız gözlemde değildir: işin kendisi de bölünmüştür ve bir değişiklik ekipten ekibe atılır. Sonraki ders aynı değişiklik kümesini iki düzende koşturur — ayrık ekipler ve paylaşılan sorumluluk — ve sınır başına beklemeyi, aktarılamayan bağlam yüzünden geri dönen değişikliği ve üretimde ortaya çıkan hata sayısını sayar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.