Ders 05 / 20
Zaman Aşımı Bütçeleri
Yavaşlayan bir bağımlılıkta bütçenin nasıl tükendiği: kola kalan payın ardışık alt çağrılara açgözlü, eşit ve ağırlıklı bölüştürülmesi, açgözlü dağıtımın sağlam adımı suçlu göstermesi, çağıranın tuttuğu yuva ile bağımlılıkta terk edilen işin ayrı ayrı sayılması ve sıkı bölüştürmenin ancak iptal sinyaliyle birlikte kazanç yazması.
İçindekiler
Yeniden deneme politikası artık kararlaştırılmış durumda: kaç kez denenecek, denemeler arasında ne kadar beklenecek, sarsıntının genişliği ne olacak. Politikanın açıkta bıraktığı tek bir sayı var ve o sayı politikanın kendisinden daha belirleyici — çağıran, vazgeçmeden önce toplam ne kadar bekleyecek. Bu süre konmadıkça geri çekilme bir sınıra doğru değil, boşluğa doğru büyür.
Uygulama Katmanı ve Servis Etkileşimi kursu bu sürenin bir bütçe olduğunu kurdu: uçtan uca eşik zincirin adımlarına bölüştürülür, kalan süre çağrıyla birlikte geçirilir ve deneme sayısı bütçeyi çarpar. O hesap burada girdidir, tekrarlanmaz. Bu dersin sorusu bir basamak sonrasıdır. Zincirdeki bir adım yavaşladığında bütçe nerede tükenir, kalan pay alt çağrılara nasıl bölünür, ve çağıran vazgeçtikten sonra bağımlılığın hâlâ yaptığı iş ne kadardır.
Arıza Kipi
Zincir bu kursun ortak yapısından gelir. Takip sorgusu ağ geçidinden girer ve iki kolu paralel çağırır. Teslimat operasyonu kolu kendi deposundan tek bir kayıt okur; ücretlendirme kolu iki kayıt okur — önce tarife, sonra gönderinin ölçüsü — ve ücreti ikisinden hesaplar. Uygulama Katmanı kursu bir dış istek için dört adım çağrısı saymıştı; ücretlendirme kolunun depo basamağı iki ardışık okumaya ayrıldığında sayı beşe çıkar.
AY10 — tarife deposu yavaşlıyor. Durmuyor, yanlış yanıt vermiyor, ağ bölünmesi yaşamıyor; yalnız yanıt süresi olağan altı milisaniyelik ortancasının onlarca katına çıkıyor. Süre 12 dakika, sıklık ayda bir kez. Gerekçe: yavaşlama bir bakım penceresiyle ya da bir sorgu planı değişikliğiyle başlar ve fark edilip geri alınana kadar sürer; on iki dakika, K01’in on dakikalık kurtarma süresi varsayımının biraz üstündedir. Duyarlılığı aşağıda hesaplanmıştır. Bu varsayım K01’in tablosuna eklenmez.
Yavaşlama, durmadan daha zor bir kiptir. Durmuş bir bağımlılık bağlantıyı hemen reddeder ve çağıran bunu milisaniyenin altında öğrenir. Yavaşlayan bağımlılık hiçbir şeyi reddetmez, yalnız bekletir — ve bekleme, hiçbir sınır konmadıysa çağıranın kaynağıyla ödenir. Bütçe bu beklemenin ne kadarının kabul edileceğine karar veren tek mekanizmadır.
Kalan Payın Bölünmesi
Kola düşen pay bellidir: K01’in 200 milisaniyelik okuma eşiğinden Uygulama Katmanı kursunun U3 varsayımı olan 20 milisaniyelik ağ geçidi payı çıkınca 180 milisaniye kalır. Ücretlendirme kolu bu 180 milisaniyeyi iki ardışık okumaya dağıtmak zorundadır ve üç politika vardır.
Açgözlü dağıtım kalanın tamamını her çağrıya verir: ilk okuma 180 milisaniyeye kadar bekleyebilir, ikincisi geriye ne kalırsa onu alır. Eşit dağıtım payı ikiye böler. Ağırlıklı dağıtım payı olağan sürelerin oranında paylaştırır; tarife 6, ölçü 12 milisaniye olduğuna göre oran bire ikidir.
Üçü de arızasız günde neredeyse aynı görünür, çünkü iki okuma da payının çok altında kalır. Ayrım, bir okuma payını aştığı anda çıkar.
// butce/zincir.mjs — takip sorgusu zincirinin MODELI. Mantiksal saat: adim sureleri bir // donguden okunur, gercek zaman olculmez; servis, ag ya da depo kurulmaz. export const K01 = { esik: 200, tepeOkuma: 416.67, tepeUc: 513.89, yanitBayt: 480 }; export const GECIT_PAYI = 20; // K03 servis-tasarimi/05, varsayim U3 export const ORTANCA = { teslimat: 8, tarife: 6, olcu: 12 }; // model parametresi (ms) const D = (govde, kuyruk) => [...govde, ...govde, kuyruk]; // 16'da bir uzun kuyruk export const REJIM = { // alt cagrinin suresi (ms), on altilik dongu arizasiz: { teslimat: D([8, 9, 8, 10, 8, 9, 8, 10], 40), tarife: D([6, 7, 6, 8, 6, 7, 6, 8], 80), olcu: D([12, 13, 12, 14, 12, 13, 12, 14], 100), }, "tarife yavas": { // AY10: yalniz tarife deposu yavasliyor teslimat: D([8, 9, 8, 10, 8, 9, 8, 10], 40), tarife: D([150, 400, 220, 400, 180, 300, 260, 400], 400), olcu: D([12, 13, 12, 14, 12, 13, 12, 14], 100), }, }; // Kola kalan payin iki ardisik alt cagriya bolusturulmesi. export function paylar(politika, kalan) { if (politika === "acgozlu") return [kalan, kalan]; if (politika === "esit") return [kalan / 2, kalan / 2]; const t = ORTANCA.tarife + ORTANCA.olcu; // agirlikli: olagan surelerin orani return [(kalan * ORTANCA.tarife) / t, (kalan * ORTANCA.olcu) / t]; } export function kosum({ rejim, politika, iptal, n = 48 }) { const R = K01.esik - GECIT_PAYI; // kola kalan pay const s = { yanit: 0, dusen: 0, bosaIs: 0, toplamSure: 0, basarisiz: { teslimat: 0, tarife: 0, olcu: 0 }, uctanUca: [] }; const imlec = { teslimat: 0, tarife: 0, olcu: 0 }; const sure = (ad) => REJIM[rejim][ad][imlec[ad]++ % REJIM[rejim][ad].length]; const cagir = (ad, zt) => { // tek alt cagri, zaman asimi zt if (zt <= 0) return { ok: false, gecen: 0 }; const su = sure(ad); if (su <= zt) return { ok: true, gecen: su }; if (iptal === false) s.bosaIs += su - zt; // cagiran vazgecti, bagimlilik calisiyor return { ok: false, gecen: zt }; }; for (let i = 0; i < n; i += 1) { const a = cagir("teslimat", R); // teslimat-op kolu: tek depo cagrisi const p = paylar(politika, R); // ucretlendirme kolu: iki ardisik kayit const b1 = cagir("tarife", Math.min(p[0], R)); const b2 = cagir("olcu", Math.min(p[1], R - b1.gecen)); for (const [ad, r] of [["teslimat", a], ["tarife", b1], ["olcu", b2]]) { if (r.ok === false) s.basarisiz[ad] += 1; } const gecen = GECIT_PAYI + Math.max(a.gecen, b1.gecen + b2.gecen); s.uctanUca.push(gecen); s.toplamSure += gecen; if (a.ok && b1.ok && b2.ok && gecen <= K01.esik) s.yanit += 1; else s.dusen += 1; } const sirali = [...s.uctanUca].sort((x, y) => x - y); return { ...s, ortanca: sirali[n >> 1], enKotu: sirali[n - 1], ortalama: s.toplamSure / n, n }; }
İki okuma da her istekte denenir; ücretlendirme kolu ikisinin sonucunu topladıktan sonra karar verir. Bu ayrıntı ölçümün taşıyıcısıdır: ilk okuma bütçeyi yerse ikinci okuma bunu kendi başarısızlığı olarak yaşar.
// butce/kosum.mjs — uc bolusturme politikasinin iki gunde karsilastirilmasi import { K01, GECIT_PAYI, ORTANCA, paylar, kosum } from "./zincir.mjs"; const R = K01.esik - GECIT_PAYI; const POLITIKA = ["acgozlu", "esit", "agirlikli"]; const CAGRI = 5; // dis istek basina alt cagri: 2 kol + 1 + 2 kayit const SON_TARIH_BAYT = 8; // kalan sureyi tasiyan alan const yuva = (ms) => (K01.tepeOkuma * ms) / 1000; // L = lambda x W console.log(`uctan uca esik ${K01.esik} ms (K01), gecit payi ${GECIT_PAYI} ms (K03/U3), kola kalan ${R} ms`); console.log(`olagan sureler: teslimat ${ORTANCA.teslimat}, tarife ${ORTANCA.tarife}, olcu ${ORTANCA.olcu} ms`); console.log(`${"politika".padEnd(11)}${"tarife payi(ms)".padStart(16)}${"olcu payi(ms)".padStart(15)}`); for (const p of POLITIKA) { const [a, b] = paylar(p, R); console.log(`${p.padEnd(11)}${a.toFixed(1).padStart(16)}${b.toFixed(1).padStart(15)}`); } for (const rejim of ["arizasiz", "tarife yavas"]) { console.log(`\n-- ${rejim} (48 dis istek, iptal sinyali yok) --`); console.log(`${"politika".padEnd(11)}${"yanit".padStart(6)}${"dusen".padStart(6)}${"suc:tarife".padStart(11)}` + `${"suc:olcu".padStart(9)}${"ortanca".padStart(8)}${"en kotu".padStart(8)}${"ort.".padStart(7)}` + `${"tutulan yuva".padStart(13)}${"bosa is(ms)".padStart(12)}`); for (const p of POLITIKA) { const r = kosum({ rejim, politika: p, iptal: false }); console.log(`${p.padEnd(11)}${String(r.yanit).padStart(6)}${String(r.dusen).padStart(6)}` + `${String(r.basarisiz.tarife).padStart(11)}${String(r.basarisiz.olcu).padStart(9)}` + `${String(r.ortanca).padStart(8)}${String(r.enKotu).padStart(8)}${r.ortalama.toFixed(1).padStart(7)}` + `${yuva(r.ortalama).toFixed(1).padStart(13)}${String(r.bosaIs).padStart(12)}`); } } console.log(`\n-- tarife yavas: sistemin mesgul tuttugu yuva (tepe okuma ${K01.tepeOkuma}/s) --`); console.log(`${"politika".padEnd(11)}${"cagiran".padStart(9)}${"terk edilen".padStart(12)}` + `${"toplam(iptalsiz)".padStart(17)}${"toplam(iptalli)".padStart(16)}`); for (const p of POLITIKA) { const r = kosum({ rejim: "tarife yavas", politika: p, iptal: false }); const c = yuva(r.ortalama), t = yuva(r.bosaIs / r.n); console.log(`${p.padEnd(11)}${c.toFixed(1).padStart(9)}${t.toFixed(1).padStart(12)}` + `${(c + t).toFixed(1).padStart(17)}${c.toFixed(1).padStart(16)}`); } const bayt = K01.tepeUc * CAGRI * SON_TARIH_BAYT; const a = kosum({ rejim: "arizasiz", politika: "acgozlu", iptal: false }); console.log(`\n-- arizasiz gunun bedeli (hesap) --`); console.log(`son tarih alani ${SON_TARIH_BAYT} B x ${CAGRI} alt cagri = ${CAGRI * SON_TARIH_BAYT} B/istek,` + ` takip yanitinin (${K01.yanitBayt} B) %${((CAGRI * SON_TARIH_BAYT) / K01.yanitBayt * 100).toFixed(1)}`); console.log(`tepe ucta ${K01.tepeUc} istek/s -> ${bayt.toFixed(2)} B/s = ${(bayt / 1024).toFixed(2)} KiB/s`); for (const p of ["esit", "agirlikli"]) { const r = kosum({ rejim: "arizasiz", politika: p, iptal: false }); const fark = r.dusen - a.dusen; console.log(`${p.padEnd(11)}: acgozluye gore ${fark}/${r.n} fazladan dusen istek` + ` = %${((fark / r.n) * 100).toFixed(2)} -> tepe okumada ${((K01.tepeOkuma * fark) / r.n).toFixed(2)} istek/s`); } console.log(`\n-- AY10'un duyarliligi: tarifenin yavas kaldigi sure --`); console.log(`${"sure(dk)".padStart(9)}${"ayda".padStart(6)}${"aylik(dk)".padStart(11)}${"ariza payinin(28,2 dk)".padStart(23)}`); for (const [dk, kez] of [[12, 1], [12, 2], [24, 1]]) { console.log(`${String(dk).padStart(9)}${String(kez).padStart(6)}${String(dk * kez).padStart(11)}` + `${`%${(((dk * kez) / 28.2) * 100).toFixed(1)}`.padStart(23)}`); }
uctan uca esik 200 ms (K01), gecit payi 20 ms (K03/U3), kola kalan 180 ms
olagan sureler: teslimat 8, tarife 6, olcu 12 ms
politika tarife payi(ms) olcu payi(ms)
acgozlu 180.0 180.0
esit 90.0 90.0
agirlikli 60.0 120.0
-- arizasiz (48 dis istek, iptal sinyali yok) --
politika yanit dusen suc:tarife suc:olcu ortanca en kotu ort. tutulan yuva bosa is(ms)
acgozlu 48 0 0 0 40 200 46.2 19.2 0
esit 46 2 0 2 40 190 45.8 19.1 20
agirlikli 46 2 2 0 40 180 45.3 18.9 40
-- tarife yavas (48 dis istek, iptal sinyali yok) --
politika yanit dusen suc:tarife suc:olcu ortanca en kotu ort. tutulan yuva bosa is(ms)
acgozlu 6 42 36 42 200 200 197.8 82.4 5540
esit 0 48 48 2 123 200 126.0 52.5 9700
agirlikli 0 48 48 0 93 180 96.4 40.2 11120
-- tarife yavas: sistemin mesgul tuttugu yuva (tepe okuma 416.67/s) --
politika cagiran terk edilen toplam(iptalsiz) toplam(iptalli)
acgozlu 82.4 48.1 130.5 82.4
esit 52.5 84.2 136.7 52.5
agirlikli 40.2 96.5 136.7 40.2
-- arizasiz gunun bedeli (hesap) --
son tarih alani 8 B x 5 alt cagri = 40 B/istek, takip yanitinin (480 B) %8.3
tepe ucta 513.89 istek/s -> 20555.60 B/s = 20.07 KiB/s
esit : acgozluye gore 2/48 fazladan dusen istek = %4.17 -> tepe okumada 17.36 istek/s
agirlikli : acgozluye gore 2/48 fazladan dusen istek = %4.17 -> tepe okumada 17.36 istek/s
-- AY10'un duyarliligi: tarifenin yavas kaldigi sure --
sure(dk) ayda aylik(dk) ariza payinin(28,2 dk)
12 1 12 %42.6
12 2 24 %85.1
24 1 24 %85.1
Bütün sayılar hesap sınıfındadır: belirlenimli bir süre dizisi üzerinde sayılmışlardır. Süre birimi mantıksal bir saattir, ölçülmüş gecikme değildir; koşum makineden bağımsız aynı çıktıyı verir.
Arızasız Günün Bedeli
Bütçenin iki kalemi arızasız günde de ödenir.
Birincisi taşınan alandır. Kalan süreyi çağrıyla birlikte geçirmek her alt çağrıya sekiz baytlık bir alan ekler; beş alt çağrıda dış istek başına 40 bayt eder. Bu, K01’in 480 baytlık takip yanıtının yüzde 8,3’üdür ve uçtaki tepe hızda saniyede 20,07 KiB’lik bir iç trafiktir. Küçük ama sıfır değil, ve zincir derinleştikçe doğrusal büyür.
İkincisi daha pahalıdır: sıkı bölüştürme, sağlam istekleri keser. Arızasız rejimde açgözlü dağıtım kırk sekiz isteğin kırk sekizini yanıtlıyor. Eşit ve ağırlıklı dağıtım kırk altısını yanıtlıyor; ikisi de iki isteği düşürüyor. Bunlar hiçbir arızanın olmadığı bir gündeki yanlış pozitiflerdir — modelde on altıda bir gelen uzun kuyruk, adımın payını aşıyor. Oran yüzde 4,17; K01’in tepe okuma hızında saniyede 17,36 istek eder. Hangi adımın kesildiği de politikaya bağlı: eşit dağıtımda ölçü (payı 90, kuyruğu 100), ağırlıklı dağıtımda tarife (payı 60, kuyruğu 80).
Payı adımın kuyruğuna göre seçmek bu bedeli düşürür ama sıfırlamaz. Bütçe bölüştürmesi bir kuyruk kesme kararıdır ve kesilen kuyruk her zaman gerçek isteklerden oluşur.
Arızalı Günde Ne Değişiyor
İkinci tablo AY10 altında koşuyor ve üç politikanın üç ayrı davranış ürettiğini gösteriyor.
Açgözlü dağıtım altı isteği kurtarıyor. Tarife kimi turlarda 150 ya da 180 milisaniyede dönüyor; 180 milisaniyelik payla bunlar başarılı olur ve geriye ölçüye yetecek kadar kalır. Eşit ve ağırlıklı dağıtımda aynı okumalar 90 ve 60 milisaniyede kesilir, kırk sekiz isteğin kırk sekizi düşer. Bu, sıkı bölüştürmenin bedelinin arızalı günde de sürdüğü anlamına gelir — kurtarılabilir istekler kurtarılmaz.
Karşılığı uçtan uca sürede. Açgözlü dağıtımda ortanca 200 milisaniye: her düşen istek bütçenin
tamamını yiyor. Eşit dağıtımda 123, ağırlıklı dağıtımda 93 milisaniye. Çağıran, aynı başarısızlığı
yarıdan kısa sürede öğreniyor. Bunun kaynak karşılığı tutulan yuva sütunudur: kuyruk kuramının
bağıntısıyla, K01’in 416,67 istek/s tepe okuma hızında açgözlü dağıtım 82,4,
ağırlıklı dağıtım 40,2 eşzamanlı çağıran yuvasını meşgul tutuyor. Bağıntı bu kursun bulgusu değil;
arka plan işleri konusunda kurulmuştu ve burada bir çevirici olarak kullanılıyor.
Suç sütunları arıza kipini gizliyor. Açgözlü dağıtımda tarife otuz altı kez başarısız, ölçü kırk iki kez. Ölçünün rejimi hiç değişmedi; kırk iki başarısızlığın tamamı, tarifenin bütçeyi yemesinden geliyor. Ağırlıklı dağıtımda ölçü sıfır kez başarısız. Aradaki fark bir kayıt farkı değil, bir teşhis farkıdır: açgözlü dağıtım, yavaşlayan adımı sağlam adımın arkasına saklar ve zaman aşımı kayıtlarında en çok görünen ad, arızanın yaşandığı yerin adı olmaz.
Bu, bütçe üzerinden bulaşmadır. Adımlar birbirinden yalıtılmış görünür — ayrı depolar, ayrı kayıtlar — ama paylaştıkları tek bir kaynak vardır ve o kaynak süredir. Payı sabitlemek, o tek paylaşılan kaynağı bölmenin adıdır.
Terk Edilen İş
Son sütun buraya kadarki tabloyu tersine çeviriyor. Çağıran vazgeçtiğinde tarife deposu durmaz;
başlattığı okumayı bitirir. Bu iş kimsenin beklemediği iştir ve modelde bosa is olarak sayılır:
açgözlü dağıtımda 5540, ağırlıklı dağıtımda 11120 milisaniye. Sıkı bölüştürme, terk edilen işi
iki katına çıkarıyor — çünkü daha erken vazgeçmek, bağımlılığın önünde daha uzun bir artık
bırakmak demektir.
Üçüncü tablo iki tarafı toplayarak kararı veriyor. İptal sinyali yokken sistemin meşgul tuttuğu toplam yuva açgözlüde 130,5, eşitte ve ağırlıklıda 136,7. Neredeyse aynı sayı: bölüştürme, yükü çağırandan bağımlılığa taşımaktan başka bir şey yapmıyor. Sıkı bölüştürmenin kazancı ancak iptal sinyali varken görünür — çağıran vazgeçtiğini bağımlılığa bildirir ve okuma durdurulur. O zaman terk edilen iş sıfırlanır ve toplam yuva 82,4’e karşı 40,2 olur.
Karar cümlesi budur: son tarih aktarımı iptal sinyali olmadan tamamlanmış sayılmaz. Kalan süreyi çağrıyla geçirmek, çağıranın ne zaman vazgeçeceğini söyler; iptal sinyali, vazgeçtiğini söyler. Birincisi olmadan bütçe bölüştürülemez, ikincisi olmadan bölüştürme yalnız yer değiştirir.
Son tablo AY10’un duyarlılığıdır. On iki dakikalık tek bir yavaşlama, K01’in aylık 28,2 dakikalık arıza payının yüzde 42,6’sını harcar. Aynı yavaşlama ayda iki kez olursa ya da bir kez yirmi dört dakika sürerse pay yüzde 85,1’e çıkar ve ayın kalanına 4,2 dakika kalır. Bütçe bölüştürmesi bu dakikaları geri getirmez — istekler yine düşüyor — ama düşen isteğin kaç kaynağı meşgul ettiğini belirler ve arızanın hangi adımda göründüğünü doğrular.
Özet
- Kola kalan pay (200 ms eşik eksi 20 ms ağ geçidi payı = 180 ms) ardışık alt çağrılara üç biçimde dağıtılır: açgözlü 180/180, eşit 90/90, ağırlıklı 60/120.
- Arızasız günün bedeli iki kalemdir: son tarih alanı dış istek başına 40 bayt (yanıtın yüzde 8,3’ü, tepe uçta 20,07 KiB/s) ve sıkı bölüştürmenin kestiği geçerli istekler — 48’de 2, yüzde 4,17, tepe okumada saniyede 17,36 istek.
- AY10 altında açgözlü dağıtım altı isteği kurtarır ama uçtan uca ortancayı 200 ms’de tutar; ağırlıklı dağıtım hiçbirini kurtarmaz ve ortancayı 93 ms’ye indirir, tutulan yuvayı 82,4’ten 40,2’ye düşürür.
- Açgözlü dağıtımda sağlam adım (ölçü) kırk iki kez başarısız görünür, ağırlıklı dağıtımda sıfır kez; bölüştürme yalnız kaynak değil, arıza kipinin teşhisini de belirler.
- Sıkı bölüştürme terk edilen işi 5540’tan 11120 milisaniyeye çıkarır; iptal sinyali yokken toplam meşgul yuva 130,5’e karşı 136,7’dir, yani kazanç yoktur. İptal sinyaliyle toplam 82,4’e karşı 40,2 olur — bölüştürme ancak iptalle birlikte kazanç yazar.
- On iki dakikalık tek bir yavaşlama K01’in aylık 28,2 dakikalık arıza payının yüzde 42,6’sını harcar; ayda iki kez olursa yüzde 85,1.
Sonraki Adım
Bütçe, tek bir isteğin ne kadar bekleyeceğine karar verdi ve bu kararı zincire dağıttı. Sessiz kalan bir varsayım vardı: çağıran her istek için çağrıyı yapabiliyor. Yavaşlayan bağımlılık karşısında bütçe isteği keser, kaynağı geri alır, arızayı doğru adımda gösterir — ama bir sonraki isteğin gelmesini engellemez. İstekler aynı hızla gelmeye devam eder ve her biri aynı bütçeyi aynı yavaş adıma harcar. Aynı sorunun ikinci yüzü yazma yolundadır: taşıyıcıdan gelen durum olayları sabit bir hızla akar, izdüşümü besleyen tüketici yavaşlarsa iş bir yerlerde birikir ve bütçe o birikime dokunmaz. Sonraki ders bu birikimi ele alır ve soruyu tersine çevirir: sistem, artık yetişemediğini kendisine iş veren tarafa nasıl bildirir, o bildirim zincirde nereye kadar yayılır ve bildirim hiç yapılmazsa iş nerede toplanır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.