Ders 07 / 20
Kısıtlama ve Yük Boşaltma
Denetimli hizmet reddinin iki ayrı kararı: kısıtlamanın bilinen bir hızın üstünü kaynakta kesmesi, yük boşaltmanın anlık kapasiteye göre sınıf sırasıyla reddetmesi, kısıtlamanın kapasite kaybını göremeyip yük boşaltmanın boş kapasiteyi kullandırması ve iki mekanizmanın birlikte K01'in 513,89 istek/s tepesinin ne kadarını koruduğunun sayılması.
İçindekiler
Bir önceki ders geri basınç sinyalini servis sınırına kadar taşıdı ve orada bir redde dönüştüğünü gösterdi. Reddin kendisi tasarlanmadı: tampon doluysa reddet kuralı, hangi isteğin gideceğini seçmiyordu. Uçta saniyede 513,89 istek var ve üç akış aynı kapıdan geçiyor — takip sorgusu, taşıyıcı durum olayı, gün sonu ücretlendirme isteği. Kapasite yetmediğinde hepsi eşit mi kısılacak.
Soruda birbirine karışan iki karar var; bu ders onları ayırır.
İki Ayrı Ölçüt
Kısıtlama (throttling), bilinen bir hızın üstünü kesmektir. Ölçütü akışın kendisidir: her akış için olağan hızından türetilmiş bir tavan konur ve tavanı aşan istek reddedilir. Karar sistemin o anki durumuna bakmaz — kapasite bomboş olsa da tavanı aşan istek geçmez.
Yük boşaltma (load shedding), anlık kapasiteye göre reddetmektir. Ölçütü sistemin o anki doluluğudur: kapasite yeterken hiçbir istek reddedilmez, doygunluğa yaklaşıldığında bir sınıf sırasına göre reddedilir. Aynı istek, sistem boşken kabul edilir, doluyken reddedilir.
Kabul denetimi, eşiğin eşzamanlılığa konması ve yük boşaltmanın çöküşü önlemesi Önbellekleme, Kuyruklar ve Eşzamansız İşleme kursunda kuruldu; eşik hesabı burada tekrarlanmaz. Buradaki soru ikisinin birlikte ne yaptığıdır.
İki adlandırma karışıklığı baştan ayrılmalıdır. Trafik Katmanı kursundaki ağ geçidi yük
boşaltma (gateway offloading) bu kavramla aynı sözcüğü taşır ama ayrı bir şeydir: o, kimlik
doğrulama ya da TLS sonlandırma gibi bir işi uygulamadan alıp ağ geçidine taşır — iş yine yapılır,
yeri değişir. Buradaki yük boşaltma ise isteği hiç kabul etmez. Benzer biçimde, Frontend
Kalitesi kursunda geçen kısıtlama sözcüğü bir bağlantının bant genişliğinin sınırlanmasını
anlatır; buradaki kısıtlama aynı fikrin istek hızına uygulanmış hâlidir.
Kapı
Model, uç katmandaki tek bir kabul kapısıdır; üç akış aynı kapasiteyi paylaşır ve iş birim cinsinden sayılır.
AY12 — kapasite ve birim maliyetleri. Uç katman turda 700 birim işler. Bir takip sorgusu ve bir durum olayı birer birim, bir gün sonu ücretlendirme isteği 60 birimdir. Gerekçe: toplu istek seyrek gelir ama K01’de 833,33 kayıt/s’lik bir okuma yürütür; tek bir isteğin maliyeti bu yüzden bir okuma sorgusundan iki mertebe büyüktür. Olağan talep bu değerlerle turda 603,89 birim, yani kapasitenin yüzde 86,3’ü.
AY13 — iki arıza senaryosu. AY13a: gün sonu ücretlendirme işi tepe saate taşıyor; istek hızı turda 1,5’ten 4,5’e çıkıyor, süre 30 dakika, sıklık ayda iki kez. Gerekçe: dört saatlik pencere K01’de sabittir, iş uzarsa ya da geç başlarsa tepe saate girer. AY13b: bir uç düğümü düşüyor; kapasite dörtte bir azalıyor (700 → 525), süre 8 dakika, sıklık ayda iki kez. Gerekçe: düğüm kaybı ile yerine yenisinin gelmesi K01’in on dakikalık kurtarma süresi varsayımının altında kalır. Duyarlılıkları aşağıda hesaplanmıştır. Bu varsayımlar K01’in tablosuna eklenmez.
Sınıf sırası akışların ne kaybettirdiğinden çıkar: durum olayının kaybı takip zincirini kalıcı olarak eksiltir (sınıf 1), takip sorgusunun reddi kullanıcıyı bekletir ama yeniden denenebilir (sınıf 2), gün sonu işi ertelenebilir (sınıf 3). Boşaltma en düşük sınıftan başlar.
// kapi/uc.mjs — uc katmanindaki kabul kapisinin MODELI. Tur soyut bir adimdir // (bir tur = bir saniye; cevrim katsayisi varsayim). Gercek dugum ya da sunucu kurulmaz. export const K01 = { takip: 416.67, olay: 97.22, tepeUc: 513.89 }; // AY12: birim maliyetleri ve uc kapasitesi. Bir birim = bir takip sorgusunun isi. export const AKIS = [ { ad: "olay", birim: 1, hiz: K01.olay, sinif: 1 }, // tasiyici durum yazmasi { ad: "takip", birim: 1, hiz: K01.takip, sinif: 2 }, // kullaniciya donen okuma { ad: "toplu", birim: 60, hiz: 1.5, sinif: 3 }, // gun sonu ucretlendirme istegi ]; export const KAPASITE = 700; // AY12: turda islenen birim export const TAVAN_PAYI = 1.2; // kisitlama tavani = olagan hiz x 1,2 export const SALINIM = [0.85, 0.85, 0.85, 1.45]; // takip akisinin varis salinimi export function kosum({ turSayisi, kisitlama, bosaltma, kapasite = KAPASITE, topluHizi = 1.5, salinim = true }) { const hizlar = AKIS.map((a) => (a.ad === "toplu" ? topluHizi : a.hiz)); const tavan = AKIS.map((a) => a.hiz * TAVAN_PAYI); // bilinen olagan hizdan turetilir const birikimi = AKIS.map(() => 0); const kuyruk = []; // { i, birim, tur } const s = { gelen: AKIS.map(() => 0), kabul: AKIS.map(() => 0), redKisit: AKIS.map(() => 0), redBosalt: AKIS.map(() => 0), enBuyukYas: 0, }; const SINIR = 2 * kapasite; // bir turluk is bekleyebilir for (let t = 1; t <= turSayisi; t += 1) { const gelenler = []; const kalanTavan = [...tavan]; // tavan turdan tura tasinmaz AKIS.forEach((a, i) => { // varis: kesirli hiz birikimle const carpan = a.ad === "takip" && salinim ? SALINIM[(t - 1) % SALINIM.length] : 1; birikimi[i] += hizlar[i] * carpan; while (birikimi[i] >= 1) { birikimi[i] -= 1; s.gelen[i] += 1; if (kisitlama && kalanTavan[i] < 1) { s.redKisit[i] += 1; continue; } kalanTavan[i] -= 1; gelenler.push(i); } }); let bekleyen = kuyruk.reduce((x, o) => x + o.birim, 0); gelenler.sort((x, y) => AKIS[x].sinif - AKIS[y].sinif); // once ust sinif kabul edilir for (const i of gelenler) { if (bosaltma && bekleyen + AKIS[i].birim > SINIR) { s.redBosalt[i] += 1; continue; } kuyruk.push({ i, birim: AKIS[i].birim, tur: t }); bekleyen += AKIS[i].birim; s.kabul[i] += 1; } let butce = kapasite; // turun isleme kapasitesi while (kuyruk.length > 0 && kuyruk[0].birim <= butce) { const o = kuyruk.shift(); butce -= o.birim; s.enBuyukYas = Math.max(s.enBuyukYas, t - o.tur); } } s.biriken = kuyruk.reduce((x, o) => x + o.birim, 0); s.bekleyenYas = kuyruk.length === 0 ? 0 : turSayisi - kuyruk[0].tur; return s; }
// kapi/kosum.mjs — kisitlama ile yuk bosaltmanin uc gunde ayri ayri ve birlikte olculmesi import { K01, AKIS, KAPASITE, TAVAN_PAYI, kosum } from "./uc.mjs"; const TUR = 600; // karsilastirma penceresi; toplamlar sureyle dogrusal const AYAR = [ ["hicbiri", { kisitlama: false, bosaltma: false }], ["yalniz kisitlama", { kisitlama: true, bosaltma: false }], ["yalniz bosaltma", { kisitlama: false, bosaltma: true }], ["ikisi birden", { kisitlama: true, bosaltma: true }], ]; const GUN = [ ["arizasiz", {}], ["AY13a: toplu is tepe saatte (1,5 -> 4,5 istek/tur)", { topluHizi: 4.5 }], ["AY13b: bir uc dugumu dustu (kapasite 700 -> 525)", { kapasite: 525 }], ]; const olagan = AKIS.reduce((x, a) => x + a.hiz * a.birim, 0); console.log(`kapasite ${KAPASITE} birim/tur; olagan talep ${olagan.toFixed(2)} birim/tur` + ` (doluluk %${((olagan / KAPASITE) * 100).toFixed(1)})`); console.log(`akislar: ${AKIS.map((a) => `${a.ad}(sinif ${a.sinif}, ${a.birim} birim, ${a.hiz}/tur)`).join(", ")}`); console.log(`kisitlama tavanlari (olagan hiz x ${TAVAN_PAYI}): ` + AKIS.map((a) => `${a.ad} ${(a.hiz * TAVAN_PAYI).toFixed(2)}`).join(", ")); for (const [gun, ek] of GUN) { console.log(`\n-- ${gun} --`); console.log(`${"ayar".padEnd(18)}${"karsilanan olay/takip/toplu".padStart(28)}` + `${"kisit reddi".padStart(15)}${"bosaltma reddi".padStart(16)}${"en buyuk yas".padStart(13)}` + `${"biriken".padStart(8)}${"bekleyen yas".padStart(13)}`); for (const [ad, y] of AYAR) { const r = kosum({ turSayisi: TUR, ...y, ...ek }); console.log(`${ad.padEnd(18)}${r.kabul.join("/").padStart(28)}` + `${r.redKisit.join("/").padStart(15)}${r.redBosalt.join("/").padStart(16)}` + `${String(r.enBuyukYas).padStart(13)}${String(r.biriken).padStart(8)}` + `${String(r.bekleyenYas).padStart(13)}`); } } console.log(`\n-- AY13b'de korunan tepe --`); const dus = kosum({ turSayisi: TUR, kisitlama: false, bosaltma: true, kapasite: 525 }); const korunan = (dus.kabul[0] + dus.kabul[1]) / TUR; console.log(`bosaltma acikken karsilanan olay+takip = ${korunan.toFixed(2)} istek/tur;` + ` K01 tepe uc ${K01.tepeUc} istek/s -> orani ${(korunan / K01.tepeUc).toFixed(4)}`); console.log(`toplu akisin birim yuku ${(AKIS[2].hiz * AKIS[2].birim).toFixed(2)}/tur, dugum kaybinin acigi` + ` ${(AKIS.reduce((x, a) => x + a.hiz * a.birim, 0) - 525).toFixed(2)}/tur`); const [DK, KEZ, ARIZA_PAYI] = [8, 2, 28.2]; // AY13b suresi ve K01 aylik ariza payi (dk) console.log(`kapisiz duzende AY13b bir kesintidir: ${DK} dk x ${KEZ} = ${DK * KEZ} dk/ay =` + ` K01 ariza payinin (${ARIZA_PAYI} dk) %${(((DK * KEZ) / ARIZA_PAYI) * 100).toFixed(1)}'i`); console.log(`kapili duzende ayni sure kesinti degil kismi reddir:` + ` ${(dus.redBosalt.reduce((x, y) => x + y, 0) / TUR).toFixed(2)} istek/tur reddedilir`); console.log(`\n-- arizasiz gunun bedeli --`); const k = kosum({ turSayisi: TUR, kisitlama: true, bosaltma: false }); const kd = kosum({ turSayisi: TUR, kisitlama: true, bosaltma: false, salinim: false }); const b = kosum({ turSayisi: TUR, kisitlama: false, bosaltma: true }); const h = kosum({ turSayisi: TUR, kisitlama: false, bosaltma: false }); console.log(`kisitlama: ${k.redKisit[1]} gecerli takip sorgusu reddedildi = gelenin` + ` %${((k.redKisit[1] / k.gelen[1]) * 100).toFixed(2)}, tepe okumada ${((K01.takip * k.redKisit[1]) / k.gelen[1]).toFixed(2)} istek/s`); console.log(`salinim kapatilinca ayni ayar: ${kd.redKisit[1]} red -> tavani asan sey ortalama hiz degil, tepedir`); console.log(`bosaltma: ${b.redBosalt.reduce((x, y) => x + y, 0)} red, en buyuk yas ${b.enBuyukYas} tur` + ` (kapisiz duzende ${h.enBuyukYas} tur)`); console.log(`her istek iki denetimden gecer: akis tavani ve doluluk -> istek basina 2 denetim`); console.log(`\n-- AY13'un duyarliligi --`); console.log(`${"senaryo".padEnd(26)}${"ikisi birden: olay/takip/toplu".padStart(31)}${"toplam red".padStart(11)}`); for (const [ad, ek] of [["toplu 3,0 istek/tur", { topluHizi: 3 }], ["toplu 6,0 istek/tur", { topluHizi: 6 }], ["kapasite 595 (%15 kayip)", { kapasite: 595 }], ["kapasite 455 (%35 kayip)", { kapasite: 455 }]]) { const r = kosum({ turSayisi: TUR, kisitlama: true, bosaltma: true, ...ek }); const red = r.redKisit.reduce((x, y) => x + y, 0) + r.redBosalt.reduce((x, y) => x + y, 0); console.log(`${ad.padEnd(26)}${r.kabul.join("/").padStart(31)}${String(red).padStart(11)}`); }
kapasite 700 birim/tur; olagan talep 603.89 birim/tur (doluluk %86.3) akislar: olay(sinif 1, 1 birim, 97.22/tur), takip(sinif 2, 1 birim, 416.67/tur), toplu(sinif 3, 60 birim, 1.5/tur) kisitlama tavanlari (olagan hiz x 1.2): olay 116.66, takip 500.00, toplu 1.80 -- arizasiz -- ayar karsilanan olay/takip/toplu kisit reddi bosaltma reddi en buyuk yas biriken bekleyen yas hicbiri 58331/250002/900 0/0/0 0/0/0 1 122 0 yalniz kisitlama 58331/234372/600 0/15630/300 0/0/0 0 0 0 yalniz bosaltma 58331/250002/900 0/0/0 0/0/0 1 122 0 ikisi birden 58331/234372/600 0/15630/300 0/0/0 0 0 0 -- AY13a: toplu is tepe saatte (1,5 -> 4,5 istek/tur) -- ayar karsilanan olay/takip/toplu kisit reddi bosaltma reddi en buyuk yas biriken bekleyen yas hicbiri 58331/250002/2700 0/0/0 0/0/0 67 52266 66 yalniz kisitlama 58331/234372/600 0/15630/2100 0/0/0 0 0 0 yalniz bosaltma 58331/250002/1872 0/0/0 0/0/828 1 680 0 ikisi birden 58331/234372/600 0/15630/2100 0/0/0 0 0 0 -- AY13b: bir uc dugumu dustu (kapasite 700 -> 525) -- ayar karsilanan olay/takip/toplu kisit reddi bosaltma reddi en buyuk yas biriken bekleyen yas hicbiri 58331/250002/900 0/0/0 0/0/0 81 48983 80 yalniz kisitlama 58331/234372/600 0/15630/300 0/0/0 29 15624 28 yalniz bosaltma 58331/229912/454 0/0/0 0/20090/446 1 525 0 ikisi birden 58331/229852/455 0/15630/300 0/4520/145 1 525 0 -- AY13b'de korunan tepe -- bosaltma acikken karsilanan olay+takip = 480.40 istek/tur; K01 tepe uc 513.89 istek/s -> orani 0.9348 toplu akisin birim yuku 90.00/tur, dugum kaybinin acigi 78.89/tur kapisiz duzende AY13b bir kesintidir: 8 dk x 2 = 16 dk/ay = K01 ariza payinin (28.2 dk) %56.7'i kapili duzende ayni sure kesinti degil kismi reddir: 34.23 istek/tur reddedilir -- arizasiz gunun bedeli -- kisitlama: 15630 gecerli takip sorgusu reddedildi = gelenin %6.25, tepe okumada 26.05 istek/s salinim kapatilinca ayni ayar: 0 red -> tavani asan sey ortalama hiz degil, tepedir bosaltma: 0 red, en buyuk yas 1 tur (kapisiz duzende 1 tur) her istek iki denetimden gecer: akis tavani ve doluluk -> istek basina 2 denetim -- AY13'un duyarliligi -- senaryo ikisi birden: olay/takip/toplu toplam red toplu 3,0 istek/tur 58331/234372/600 16830 toplu 6,0 istek/tur 58331/234372/600 18630 kapasite 595 (%15 kayip) 58331/234372/600 15930 kapasite 455 (%35 kayip) 58331/214820/5 36077
Bütün sayılar hesap sınıfındadır: belirlenimli bir varış dizisi üzerinde sayılmışlardır.
Arızasız Günün Bedeli
Kısıtlama arızasız günde ödetir. Takip akışının tavanı turda 500,00 istek; varış salınımı
tepede 604,17 isteğe çıkınca aradaki fark reddedilir. Altı yüz turda 15.630 geçerli takip sorgusu
gider — gelenin yüzde 6,25’i, K01’in tepe okuma hızında saniyede 26,05 istek. Salınım kapatıldığında
aynı ayar hiçbir isteği reddetmiyor; demek ki tavanı aşan şey ortalama hız değil, tepedir. Üstelik
kapasite o anda boştu (en buyuk yas ve biriken sıfır): kısıtlama, kullanılabilir kapasiteyi
kullandırmadan reddeder.
Yük boşaltma arızasız günde ödetmez. Doluluk sınırına yaklaşılmadığı için hiçbir istek
reddedilmiyor ve en buyuk yas kapısız düzendekiyle aynı: 1 tur. Bedeli redde değil, geç tepki
vermesindedir.
Ortak bedel küçüktür: her istek iki denetimden geçer, akış tavanı ve doluluk.
İki Arıza, İki Mekanizma
İkinci ve üçüncü tablolar iki mekanizmanın farklı arıza kiplerini yakaladığını gösteriyor.
AY13a’da (toplu iş tepe saate taşıyor) kısıtlama üstün. Kapısız düzende gecikme 67 tura, biriken iş 52.266 birime çıkıyor — bu bir çöküştür. Kısıtlama toplu akışın tavanını turda 1,80’de tuttuğu için 2100 fazla isteği daha kapıda keser; gecikme sıfır, biriken sıfır. Boşaltma da çöküşü önlüyor ama farklı davranıyor: boş kapasiteyi kullandırdığı için 1872 toplu isteği kabul ediyor, kısıtlamanın kabul ettiğinin 3,1 katı; karşılığı bir turluk gecikme ve 680 birimlik birikimdir.
AY13b’de (bir uç düğümü düşüyor) kısıtlama işe yaramıyor. Hiçbir akış tavanını aşmıyor — akışlar olağan hızlarında. Kısıtlama hiçbir şey reddetmiyor ve kapasite 525’e indiği için gecikme 29 tura, biriken iş 15.624 birime çıkıyor. Boşaltma aynı senaryoda gecikmeyi 1 turda, birikeni 525 birimde tutuyor.
Ayrımın kaynağı ölçüttür: kısıtlamanın tavanı bilinen bir hızdan türetilir ve kapasite değiştiğinde değişmez, bu yüzden kapasite kaybı hiçbir tavanı ihlal etmez ve kısıtlama onu göremez.
Son satır ikisini birlikte çalıştırıyor ve her iki senaryoda da en iyi sonucu veriyor: hiçbiri ötekini gereksizleştirmiyor.
Korunan Tepe
Asıl soru hangi isteğin korunduğuydu. AY13b’de boşaltma açıkken karşılanan durum olayı ile takip sorgusu toplamı turda 480,40 istek — K01’in 513,89 istek/s tepesinin 0,9348’i. Durum olayı akışının tamamı korunuyor (58.331 istek); kesilen 20.090 takip sorgusu ile 446 toplu istektir.
Aritmetiği tabloda: düğüm kaybının açığı turda 78,89 birim, toplu akışın yükü 90,00 birim. Toplu akışı tümüyle kesmek açığı kapatmaya yeter — ama boşaltma yalnız doygunlukta tepki verdiği için varış tepelerinde kuyruk sınıra dayanır ve o turlarda takip sorgusundan da kesilir. Sınıf sırası neyin önce kesileceğini belirler, hiçbir şeyin kesilmeyeceğini değil.
Kapı olmasaydı bu on altı dakika bir kesinti olurdu: gecikme 81 tura çıkıyor ve hiçbir istek zamanında karşılanmıyor. Aylık iki koşumla 16 dakika, K01’in 28,2 dakikalık arıza payının yüzde 56,7’sidir. Kapıyla birlikte aynı süre bir kesinti değil, kısmi bir reddir — bütçeye yazılan dakika sıfırdır, karşılığında turda 34,23 istek reddedilmiştir.
Son tablo duyarlılıktır. Toplu akışın hızı 3,0 da olsa 6,0 da olsa, kapasite kaybı yüzde 15’te de kalsa karşılanan istek sayısı değişmiyor: kısıtlama tavanı bağladığı için kaynaktaki anormalliğin büyüklüğü sonuca geçmiyor. Yüzde 35 kayıpta ise takip 214.820’ye, toplu akış 600’den 5 isteğe iniyor — sınıf sırası önce en düşük sınıfı tüketiyor, sonra korunan sınıfa giriyor.
Özet
- Kısıtlama bilinen bir hızın üstünü kaynakta keser (ölçüt akış), yük boşaltma anlık kapasiteye göre sınıf sırasıyla reddeder (ölçüt doluluk); Trafik Katmanı kursundaki ağ geçidi yük boşaltma işi ağ geçidine taşır, buradaki ise isteği hiç kabul etmez.
- Arızasız günün bedeli yalnız kısıtlamaya aittir: 15.630 geçerli takip sorgusu reddedilir (gelenin yüzde 6,25’i, tepe okumada 26,05 istek/s) ve salınım kapatıldığında bu sayı sıfırlanır. Boşaltma arızasız günde hiçbir isteği reddetmez.
- AY13a’da (toplu iş tepe saate taşıyor) kapısız düzen 67 turluk gecikmeyle çöküyor; kısıtlama gecikmeyi sıfırlıyor, boşaltma da çöküşü önlüyor ve boş kapasiteyi kullandırdığı için 3,1 kat daha çok toplu isteği geçiriyor.
- AY13b’de (bir uç düğümü düşüyor) kısıtlama hiçbir şey reddetmiyor ve gecikme 29 tura çıkıyor; ölçütü akış olduğu için kapasite kaybını göremiyor. Boşaltma gecikmeyi 1 turda tutuyor.
- Boşaltma AY13b’de K01’in 513,89 istek/s tepesinin 0,9348’ini koruyor ve durum olayı akışını tümüyle ayakta tutuyor; kapısız düzende aynı 16 dakika K01’in 28,2 dakikalık arıza payının yüzde 56,7’sini yerdi.
Sonraki Adım
Kapı, kabul edilen isteğe verilen sözü tuttu ve kabul edilmeyeni açıkça reddetti. Bir boşluk kaldı. AY13b’de kesilen 20.090 takip sorgusu tümüyle boşa gitti — oysa takip sorgusunun yanıtı tek parça değildir: gönderinin durumu, tahmini teslim zamanı ve ücret ayrı alanlardır ve ayrı bağımlılıklardan gelir. Bir bağımlılık düştüğünde isteğin tamamını düşürmek, elde olan alanları da atmak demektir. Sonraki ders bunu ele alır: yanıtın hangi parçasının çekirdek olduğuna karar vermek, çekirdek dışındaki alanlar gelmediğinde isteği yine de yanıtlamak ve bunun arızasız günde neye mal olduğunu saymak.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.