İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat