Ders 19 / 19
Olay Sonrası Çözümleme
Bir kesintinin bu kursta üretilen sinyallerden yeniden kurulması: altı sorunun hangi sinyalle ve kaç adımda yanıtlandığı, hiçbir sinyalin yanıtlayamadığı soruların sayılması, eylemlerin koda dönmesi ve kişi arayan çözümlemenin ürettiği eylemlerin kaçının bir sonraki olayda bir soruyu yanıtlanır kıldığı.
İçindekiler
Bir önceki ders şunu bıraktı: ölçülen boşlukların tamamı yazıldıkları anda değil, bir arıza onlara dokunduğunda öğrenildi. Öğrenmenin kendisi ise henüz bir düzenek değil.
Kök neden çözümlemesi ve neden zinciri modeli M21/K05 Otomasyon ve Altyapı kursunda kuruldu ve burada tekrarlanmaz. Buranın konusu daha dardır: olayın telemetriden yeniden kurulması. Bu ders altı soruyu gerçek bir olaya sorar, her birinin hangi sinyalle ve kaç adımda yanıtlandığını sayar, sonra çıkan eylemleri koda uygulayıp aynı soruları yeniden sorar. Adım birimi bu kursta tanımlandı: bir sinyal deposu üzerinde bir geçiş ya da iki depoyu bir anahtar üzerinden eşleştiren birleştirme.
Olay
Bildirim servisi 80. istekten 140. isteğe kadar 5 ms yerine 200 ms sürüyor. DY17 — bildirim çağrı
yerinin ne yazdığı üç bayrakla değişir; her bayrak bu olaydan çıkacak bir eylemin karşılığıdır.
Bayraklar kapalıyken sistem telemetri konusunda ölçülen durumdadır: kimliği taşımayan çağrı yeri
bildirim servisini haritanın dışında bırakır.
// servisler.mjs — 8501 odunc, 8502 bildirim, 8503 uyelik. Uc sinyal uygulama kodunda uretilir. // DY17: bildirim cagri yerinin ne yazdigi uc bayrakla degisir; her bayrak bir olay sonrasi eylemdir. import { createServer, request } from "node:http"; const S = { gunluk: [], olcut: [], iz: [] }, A = { aralik: 0, kimlik: 0, teslim: 0 }; const OLAY = [80, 140], TIK = 20, YAVAS = 200, NORMAL = 5; // olay 80. istekte baslar, 140'ta biter const olcut = (tik, servis, sure) => { // sayac + sure toplami, kimlik tasimaz const o = S.olcut.find((x) => x.tik === tik && x.servis === servis) ?? S.olcut[S.olcut.push({ tik, servis, istek: 0, toplam: 0 }) - 1]; o.istek += 1; o.toplam += sure; }; const cagir = (port, yol, kimlik) => new Promise((coz) => { const t0 = Date.now(); const r = request({ port, path: yol, agent: false, headers: kimlik ? { "x-kimlik": kimlik } : {} }, (y) => { y.resume(); y.on("end", () => coz(Date.now() - t0)); }); r.on("error", () => coz(Date.now() - t0)); r.end(); }); createServer((i, y) => { setTimeout(() => y.end("{}"), NORMAL); }).listen(8503); // uyelik: hep hizli createServer((i, y) => { // 8502 bildirim: olay penceresinde yavaslar const n = Number(new URL(i.url, "http://x").searchParams.get("n")); const gec = n >= OLAY[0] && n < OLAY[1], sure = gec ? YAVAS : NORMAL; setTimeout(() => { const kimlik = i.headers["x-kimlik"] ?? null; // eylem 2: cagri yeri kimligi tasiyor mu const k = { t: n, servis: "bildirim", kimlik, sure }; if (A.teslim) k.teslim = !gec; // eylem 3: teslim sonucu sinyale yaziliyor mu S.gunluk.push(k); if (A.aralik) S.iz.push({ kimlik, servis: "bildirim", sure }); // eylem 1: aralik yaziliyor mu olcut(Math.floor(n / TIK), "bildirim", sure); y.end("{}"); }, sure); }).listen(8502); createServer(async (i, y) => { // 8501 odunc const q = new URL(i.url, "http://x").searchParams; if (i.url === "/sinyal") return y.end(JSON.stringify(S)); if (i.url.startsWith("/kur")) { for (const k of Object.keys(A)) A[k] = Number(q.get(k)); for (const d of Object.keys(S)) S[d] = []; return y.end("{}"); } const n = Number(q.get("n")), kimlik = `odunc-${n}`, t0 = Date.now(); S.iz.push({ kimlik, servis: "uyelik", sure: await cagir(8503, "/uye", kimlik) }); if (n % 3 === 0) await cagir(8502, `/gonder?n=${n}`, A.kimlik ? kimlik : null); const sure = Date.now() - t0; S.gunluk.push({ t: n, servis: "odunc", kimlik, uye: `u${n % 25}`, sure }); S.iz.push({ kimlik, servis: "odunc", sure }); olcut(Math.floor(n / TIK), "odunc", sure); y.end("{}"); }).listen(8501);
Çözümleme
Altı soru altı işlevdir. Her biri gerçek sinyal depoları üzerinde çalışır ve her geçişte adım sayacını artırır; sayı iddia edilmez, koşumdan çıkar. Gereken alan ya da birleştirecek anahtar yoksa soru yanıtsız kalır.
// cozumle.mjs — olayin telemetriden yeniden kurulmasi: her soru hangi sinyalle ve kac adimda yanitlaniyor. import { request } from "node:http"; const N = 200, ESIK = 40, AGIR = 100; // DY18: tik ortalamasi ESIK'i, tek cagri AGIR'i asarsa olay const cagir = (yol) => new Promise((c) => request({ port: 8501, path: yol, agent: false }, (r) => { let g = ""; r.on("data", (p) => (g += p)); r.on("end", () => c(g === "{}" ? null : JSON.parse(g))); }).end()); let adim = 0; const tara = (k, f) => { adim += 1; return k.filter(f); }; // bir depoda bir gecis const birlestir = (a, b) => { // iki depoyu kimlik uzerinden eslestirme adim += 1; const m = new Map(b.map((x) => [x.kimlik, x])); return a.map((x) => m.get(x.kimlik)); }; const yavas = (x) => x.sure > AGIR; const bildirim = (S) => tara(S.gunluk, (x) => x.servis === "bildirim" && yavas(x)); const olayTik = (S) => tara(S.olcut, (x) => x.servis === "odunc" && x.toplam / x.istek > ESIK).map((x) => x.tik); const SORU = [ ["olay hangi tikte basladi", "olcut", (S) => { const t = olayTik(S); return t.length ? `tik ${Math.min(...t)}` : null; }], ["olay hangi tikte bitti", "olcut", (S) => { const t = olayTik(S); return t.length ? `tik ${Math.max(...t) + 1}` : null; }], ["hangi bagimlilik yavasladi", "iz", (S) => { const a = tara(S.iz, (x) => x.servis !== "odunc" && yavas(x)); return a.length ? [...new Set(a.map((x) => x.servis))].join("+") : null; }], ["kac istek etkilendi", "gunluk", (S) => { const b = bildirim(S); if (b.length && b[0].kimlik !== null) return `${new Set(b.map((x) => x.kimlik)).size} istek`; const o = tara(S.gunluk, (x) => x.servis === "odunc" && yavas(x)); // kimliksiz: depolar ayri ayri taranir return tara(S.olcut, (x) => x.servis === "bildirim").length ? `${o.length} istek` : null; }], ["hangi uyeler etkilendi", "gunluk", (S) => { const b = bildirim(S); if (!b.length || b[0].kimlik === null) return null; // birlestirecek anahtar yok const u = birlestir(b, tara(S.gunluk, (x) => x.servis === "odunc")); return `${new Set(u.map((x) => x.uye)).size} uye`; }], ["bildirim teslim edildi mi", "gunluk", (S) => { const b = tara(S.gunluk, (x) => x.servis === "bildirim" && x.teslim !== undefined); return b.length ? `${b.filter((x) => x.teslim === false).length} teslim yok` : null; }], ]; const kos = async (bayrak) => { await cagir(`/kur?${bayrak}`); for (let n = 0; n < N; n += 1) await cagir(`/istek?n=${n}`); const S = await cagir("/sinyal"); return SORU.map(([ad, sinyal, f]) => { adim = 0; const y = f(S); return { ad, sinyal, y, adim: y === null ? null : adim }; }); }; const YAP = [["olay anindaki hâl", "aralik=0&kimlik=0&teslim=0"], ["+ iz araligi", "aralik=1&kimlik=0&teslim=0"], ["+ bagintili kimlik", "aralik=1&kimlik=1&teslim=0"], ["+ teslim sinyali", "aralik=1&kimlik=1&teslim=1"]]; const yaz = (a, ...r) => console.log(String(a).padEnd(28) + r.map((x) => String(x).padStart(16)).join("")); const t = {}; console.log(`olay: ${N} istek, bildirim 80.-139. isteklerde 5 ms yerine 200 ms suruyor; tik = 20 istek`); yaz("yapilandirma", "yanitlanan", "yanitsiz", "adim"); for (const [ad, b] of YAP) { const r = (t[ad] = await kos(b)), v = r.filter((x) => x.y !== null); yaz(ad, v.length, r.length - v.length, v.reduce((a, x) => a + x.adim, 0)); } const g = (x) => (x.y === null ? "-" : `${x.y} (${x.adim} adim)`); console.log(`\n${"soru".padEnd(28)}${"sinyal".padEnd(9)}${"olay anindaki hâl".padEnd(24)}eylemlerden sonra`); t["olay anindaki hâl"].forEach((x, i) => console.log(x.ad.padEnd(28) + x.sinyal.padEnd(9) + g(x).padEnd(24) + g(t["+ teslim sinyali"][i]))); const EYLEM = { kisi: ["gelistiriciyle konusulur", "nobetciye egitim verilir", "rapora sorumlu yazilir"], sistem: ["iz araligi yazilir", "bagintili kimlik eklenir", "teslim sonucu yazilir"] }; console.log(`\n${"cozumleme".padEnd(28)}${"eylem".padStart(16)}${"koda donen".padStart(16)}${"yanitlanan soru".padStart(16)}`); for (const [tur, ad, yer] of [["kisi", "kisi arayan", "olay anindaki hâl"], ["sistem", "sistem arayan", "+ teslim sinyali"]]) yaz(ad, EYLEM[tur].length, tur === "sistem" ? EYLEM[tur].length : 0, t[yer].filter((x) => x.y !== null).length); process.exit(0);
node servisler.mjs > /dev/null 2>&1 & SP=$! sleep 1; node cozumle.mjs; kill $SP
olay: 200 istek, bildirim 80.-139. isteklerde 5 ms yerine 200 ms suruyor; tik = 20 istek yapilandirma yanitlanan yanitsiz adim olay anindaki hâl 3 3 5 + iz araligi 4 2 6 + bagintili kimlik 5 1 7 + teslim sinyali 6 0 8 soru sinyal olay anindaki hâl eylemlerden sonra olay hangi tikte basladi olcut tik 4 (1 adim) tik 4 (1 adim) olay hangi tikte bitti olcut tik 7 (1 adim) tik 7 (1 adim) hangi bagimlilik yavasladi iz - bildirim (1 adim) kac istek etkilendi gunluk 20 istek (3 adim) 20 istek (1 adim) hangi uyeler etkilendi gunluk - 20 uye (3 adim) bildirim teslim edildi mi gunluk - 20 teslim yok (1 adim) cozumleme eylem koda donen yanitlanan soru kisi arayan 3 0 3 sistem arayan 3 3 6
Çizelge Kaç Adımda Kuruluyor
Olay anındaki sinyallerle altı sorunun üçü yanıtlanabiliyor: başlangıç ve bitiş ölçütten birer adımda, kaç isteğin etkilendiği günlükten üç adımda. Kalan üçü boş.
“Kaç istek etkilendi” satırı bağıntı kimliğinin ne yaptığını gösteriyor: aynı yanıt, aynı 20 sayısı, 3 adım yerine 1 adım. Kimlik yokken bildirim kaydı hangi isteğe ait olduğunu söyleyemiyor, bu yüzden ödünç günlüğü ve ölçüt ayrı ayrı taranıyor ve tarama sayısı servis sayısıyla büyür. Zaman sorularının maliyeti ise hiç değişmiyor, çünkü ölçüt birleştirmeye ihtiyaç duymuyor. Çizelgenin iskeleti en ucuz sinyalden kuruluyor, ayrıntısı en pahalısından.
Telemetri Boşluğu
Üç soru olay anında hiçbir sinyalle yanıtlanamıyor ve nedenleri ayrıdır.
“Hangi bağımlılık yavaşladı” yanıtsız, çünkü bildirim çağrı yeri iz aralığı yazmıyor. İz deposunda ödünç aralığı yavaş görünüyor ama o yalnızca beklediğini söylüyor; bir servisin kendi yavaşlığı ile bağımlılığı beklemesi çocuk aralık olmadan ayrılamaz.
“Hangi üyeler etkilendi” yanıtsız, çünkü üye alanı yalnız ödünç kaydında, yavaşlık yalnız bildirim kaydında. İki depo da var, iki alan da var; eksik olan yalnızca ortak anahtardır — veri toplanmıştır, birleştirilemez.
“Bildirim teslim edildi mi” yanıtsız, çünkü teslim sonucu hiçbir yere yazılmıyor. Üç boşluk da birer yazma kararının sonucudur ve okuma zamanında değil, yazma zamanında kapatılabilir.
Suçsuzluk Bir Ölçüye Bağlanır
Suçsuzluk bir görgü kuralı değil, eylemin türüyle ilgili bir ölçüttür. Son tablo aynı olayın iki çözümlemesini karşılaştırıyor. Kişi arayan çözümleme üç eylem üretti; üçünün de koda dönüşü yok ve bir sonraki benzer olayda aynı üç soru yine yanıtsız kalır. Sistem arayanın üç eylemi ise birer yazma kararıdır, üçü de koda döndü ve altı sorunun altısı yanıtlanır oldu.
Ölçü şudur: bir eylem, bir sonraki benzer olayda bir sorunun yanıtını değiştiriyorsa koda dönmüştür. Bedeli ilk tablodadır: adım 5’ten 8’e çıktı, yani kapatılan soru başına bir adım.
Özet
- Olayın çizelgesi bu kursta üretilen üç sinyalden kuruldu; kök neden çözümlemesi ve neden zinciri modeli M21/K05’te kuruldu ve burada tekrarlanmadı.
- Olay anındaki sinyallerle altı sorunun üçü yanıtlandı (5 adım), üçü yanıtsız kaldı; eylemlerden sonra altısı da yanıtlandı (8 adım). Zaman soruları her yapılandırmada 1 adım, bağıntı kimliği ise yanıtı değil maliyeti değiştirdi: aynı 20 sayısı 3 adım yerine 1 adımda çıktı.
- Üç boşluğun üçü de yazma kararıdır: yazılmayan iz aralığı bağımlılığı gizledi, taşınmayan kimlik iki deponun birleşmesini engelledi, kaydedilmeyen teslim sonucu soruyu kapattı.
- Kişi arayan çözümlemenin 3 eyleminin 0’ı koda döndü ve yanıtlanan soru 3’te kaldı; sistem arayanın 3 eyleminin 3’ü döndü ve yanıt 6’ya çıktı. Bedeli üç adımdır.
Kurs Kapanışı
| Ders | Kodda nereye yerleşti | Sarmalanan / atlanan çağrı yeri | Yanlış ayarın bedeli |
|---|---|---|---|
| telemetri/01 Üç Sinyal | üçü aynı istekten aynı süreçte | ölçüt 6, günlük 11–12 adım; 9 denemenin 5’i yanıtsız | ölçüt kimlik sorusunu sonsuza kapatır |
| telemetri/02 Yapılandırılmış Günlükleme | alan tabanlı kayıt; kimlik istemci yardımcısında | 11 → 7 adım; kimlikle önceki yanıtsız soru 8 adımda | kimliği taşıyan çağrı yeri 4’te 3; bir servis harita dışı |
| telemetri/03 Ölçüt Türleri | sayaç, ölçer ve histogram çağrı yerinde | üç tip üç ayrı soru; hiçbiri ötekini yanıtlamaz | ölçer 2000 gözlemin 20’sini gördü, tepe 293 yerine 199 |
| telemetri/04 Dağıtık İzleme | iz bağlamı tek başlıkta, süreç sınırından geçer | 100 istek → 100 tam iz, 400 bağlı aralık | bağlamsız tek çağrı yeri 100 kopuk iz; en düşük oranda 40 sorunlu isteğin 0’ı |
| telemetri/05 Enstrümantasyon Standartları | toplayıcı arayüzün arkasında | toplayıcı adı 5 uygulama dosyasında → 0’ında | bağlı yerleşimde geçiş 5 dosyaya, arayüzlüde 1 dosyaya dokunur |
| telemetri/06 Bağıntılandırma | üç sinyal aynı kimlikle tek olayda | 20 adım / 3 sinyal → 2 adım / 1 sinyal | oran 0,50’de 100 olayın 51’i izsiz kalır |
| servis-duzeyi/01 Gösterge, Hedef ve Anlaşma | hariç tutma listesi süzgeç dizisi olarak | 1.188.000 kayıttan üç tanım ve dört süzgeçle 12 sayı | süzgeç dizisi anlaşma metninden ayrışırsa ölçülen ile taahhüt ayrışır |
| servis-duzeyi/02 Altın Sinyaller | doygunluk kuyruk derinliği olarak istek kaydında | 6 olay sınıfı; tek sinyal en çok 3’ünü yakalar | trafik çöküşünde hata oranı 0; 162 boş tetiğin 136’sı düşük trafikte |
| servis-duzeyi/03 Hata Bütçesi | yayın kapısı tek satırlık koşul | 30 günde 3.060 kötü isteklik bütçe; %20,6’sını taban yer | 10 yayın bütçenin %180,5’ini yedi; kapı aşımı 2.463 → 471 |
| servis-duzeyi/04 Uyarı Tasarımı | kural nedenden mi belirtiden mi okuyor | 12 kural 81 uyarı, 4 kural 9 uyarı; ikisi de 4/6 olay | neden tabanlı kümede 67 uyarı boşa, olay başına 3,5 uyarı |
| servis-duzeyi/05 Sağlık Uçları | canlılık ile hazır olma tek koşul teriminde ayrılır | 25 tiklik kesinti: 0’a karşı 4 yeniden başlatma | yanlış sınıflandırma 48 ilgisiz isteği düşürdü, toparlanma 0 → 4 tik |
| dayaniklilik/01 Zaman Aşımları | çağrı yerinde 53 satır, sarmalayıcıda 28 satır | 7 / 0 ve 6 / 1 | iç sınır dıştan büyükse 10 isteğin 10’unda öksüz tamamlanma |
| dayaniklilik/02 Yeniden Deneme ve Geri Çekilme | sarmalayıcı 6, ara katman 2, ağ geçidi 6 satır | gövdedeki 2 çağrı yerinin 1’i yeniden denenir | üç katman birden açıkken 1 istek 27 çağrı ve 27 teslim |
| dayaniklilik/03 Devre Kesici | durum anahtarı: bağımlılık başına 2, çağrı yeri başına 4 | 3 çağrı yeri; eşik 10’da 1’inin kesicisi hiç açılmaz | aynı eşikte bağımlılığa çağrı 5 → 13; seyrek yol korumasız |
| dayaniklilik/04 Bölme Kalıbı | havuz tanımı 5 satır, tek yerde | 2 çağrı yeri değişmedi; 8 çağrı yeri havuzu atlar | havuz 4 derken bağımlılık 12 görür; 40 yuva sınırı hiç bağlamaz |
| dayaniklilik/05 Zarif Bozulma | şema nesnesinde; çağrı yerinde 7, sarmalayıcıda 12 satır | 14 çağrı yerinin 6’sı sarılı, 2’si atlanmış | işaretsiz yedek, borcu gerçekten sıfır olan üyeden ayırt edilemez |
| dayaniklilik/06 Hız Sınırlama ve Kısıtlama | ağ geçidinde ve servis içi ara katmanda | 8 yol-erişim çiftinin 2’si / 6’sı; 2’si hiçbirinde | sabit anahtarda tavan 20, üye anahtarında 100.000 |
| dayaniklilik/07 Arıza Kipleri | hata kimliği dört ayrı yerden okunur | 8 kipin 5’i kalıp yığınında, 3’ü hiç görülmez | 8 kipin 6’sında çağrı yerine sıfır ulaşır, 1’i işaretsiz |
| dayaniklilik/08 Olay Sonrası Çözümleme | eylem yeni sinyal, kimlik ve aralık olarak koda döner | 6 sorunun 3’ü yanıtsız → 0’ı | kişi arayan çözümlemenin 3 eyleminin 0’ı koda döner |
Tablo tek bir kuralın on dokuz kez uygulanmasıdır. Bir kalıbın etkisi Dayanıklılık ve Güvenilirlik kursunda ölçüldü; burada ölçülen, o kalıbın kodda nereye yerleştiği ve neyi atladığıdır. Aynı kural sinyaller için de geçerliydi: izleme kategorileri başka yerde kuruldu, burada sinyalin kodda nasıl üretildiği ve hangi soruyu kaç adımda yanıtladığı sayıldı. Üçüncü sütun neredeyse her satırda aynı şeyi söylüyor — kapsanmayan yer yapılandırmada değil, yalnız kaynakta görünür.
Sistem artık görünür durumda ve arızaya dayanıyor: bir isteğin nerede yavaşladığı izlenebiliyor, göstergeler karara dönüşüyor, kalıplar arızayı çevreliyor ve kesintiden sonra çizelge kurulabiliyor. Yine de hiçbir ölçüm tek bir soruyu sormadı: isteğin kendisi kötü niyetliyse. Bütün sayılar çağıranın sistemi yormaya çalışmadığını varsaydı; yayının kendisi de hiç ele alınmadı. M16/K08 Sunucu Güvenliği ve Üretime Alma bu iki soruyla başlar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.