Bu qatlamda nima bor
Core darslik asoslarni berdi. Bu Deep qatlam senior darajadagi chuqur mexanikani ochadi: circuit breaker ichki ishlashi va sozlash, adaptiv timeout va deadline propagation, retry budget va hedged requests, bulkhead o‘lchamlash (Little qonuni) va backpressure, load shedding algoritmlari, self-healing halqasi, idempotency key va "effectively-once", hamda chaos engineering. Oxirida — senior cheklist.
Circuit breaker ichki mexanika
sliding window · slow-callCore’da circuit breaker’ning uch holatini ko‘rdik. Senior uning ichki mexanikasini va har sozlamaning ta’sirini biladi — noto‘g‘ri sozlangan breaker foyda o‘rniga zarar keltiradi.
Sliding window — qaror qanday qilinadi
Breaker "ochilishni" har xatoda emas, oyna (sliding window) statistikasi asosida hal qiladi: oxirgi N chaqiruv (count-based) yoki oxirgi T vaqt (time-based) ichidagi xato foizi. Bu tebranishni silliqlaydi.
# Circuit breaker ichki sozlamalari (resilience4j uslubi)
slidingWindowType: COUNT_BASED # oxirgi N chaqiruv oynasi (yoki TIME_BASED)
slidingWindowSize: 100 # 100 ta chaqiruv kuzatiladi
minimumNumberOfCalls: 20 # kamida 20 ta bo'lmasa OCHILMAYDI (kam namunaga trip yo'q)
failureRateThreshold: 50 # 50% xato -> OPEN
slowCallRateThreshold: 80 # 80% "sekin" ham -> OPEN (xato bo'lmasa ham!)
slowCallDurationThreshold: 2s # 2s dan uzoq = "sekin"
waitDurationInOpenState: 10s # OPEN'da 10s kutadi -> keyin HALF-OPEN
permittedNumberOfCallsInHalfOpenState: 5 # HALF-OPEN'da 5 ta sinov
1. minimumNumberOfCalls — kam namunaga trip qilmaslik uchun. 2 tadan 1 tasi fail bo‘lsa (50%) darhol ochilmasin — kamida 20 ta bo‘lsin. 2. slowCallRateThreshold — breaker faqat xatoga emas, sekin chaqiruvlarga ham ochilishi kerak: sekin xizmat oqimlarni yeydi (kaskad), garchi "xato" qaytarmasa ham. Buni ko‘pchilik unutadi.
Adaptiv timeout va deadline propagation
deadline · gRPCStatic timeout qo‘pol: juda qisqa bo‘lsa — normal so‘rovlarni kesadi; juda uzun bo‘lsa — kaskadga imkon beradi. Senior adaptiv timeout va deadline propagationni biladi.
Adaptiv timeout
Belgilangan raqam o‘rniga — kuzatilgan kechikishga qarab: masalan, timeout = p99 × 1.5. Xizmat sekinlashsa, timeout ham moslashadi. Bu normal o‘zgaruvchanlikni kesmasdan, haqiqiy osilishni ushlaydi.
Deadline propagation — behuda ishni yo‘qotish
Foydalanuvchi 2s kutadi, keyin ketadi. Lekin so‘rov ichkarida A→B→C bo‘ylab ketyapti — C hali ishlayapti, garchi chaqiruvchi allaqachon voz kechgan. Bu — behuda ish, resurs isrofi.
Yechim: so‘rovga umumiy deadline (absolyut vaqt) ber; har hop qolgan vaqtni hisoblab, undan ko‘p ishlamaydi va keyingisiga uzatadi:
// DEADLINE PROPAGATION: umumiy muddat; har hop QOLGANini uzatadi
async function callWithDeadline(deadline: number) { // deadline = absolyut vaqt (ms)
const remaining = deadline - Date.now();
if (remaining <= 0) throw new DeadlineExceeded(); // vaqt tugadi -> ishlamay xato ber
return this.http.get(url, {
timeout: remaining, // qolgan vaqtdan ko'p kutma
headers: { "x-deadline": String(deadline) }, // keyingi xizmat ham QOLGANini biladi
});
}
// -> hech bir xizmat "chaqiruvchi allaqachon voz kechgan" so'rovga ishlamaydi (behuda ish yo'q)
Retry budget va hedged requests
retry budget · hedgingCore’da retry’ni ko‘rdik. Senior darajada uni byudjet bilan cheklaydi va tail latency uchun hedged requests ishlatadi.
Retry budget — bo‘ronni matematik to‘xtatish
"3 marta retry" yetarli emas: ommaviy nosozlikda har mijoz 3x yuboradi → yuk 4x. Retry budget — retry’larni umumiy trafikning foizi sifatida cheklaydi (masalan, 10%). Byudjet tugasa — retry qilinmaydi, tizim himoyalanadi:
// RETRY BUDGET: retry'lar umumiy trafikning ~10%idan oshmasin (retry storm'ni to'sadi)
if (this.retryBudget.tryAcquire()) { // token bucket: har request byudjet qo'shadi
await retryWithBackoff(() => call());
} else {
throw err; // byudjet tugadi -> retry YO'Q (tizimni himoya)
}
Hedged requests — tail latency’ga qarshi
p99 kechikish odatda bitta sekin replika tufayli. Hedged (backup) request: birinchi so‘rov p95’dan sekinlashsa — ikkinchisini boshqa replikaga yuborasan, qaysi biri oldin kelsa — o‘shani olasan:
// HEDGED REQUEST: birinchi so'rov p95'dan sekinlashsa -> ikkinchisini boshqa replikaga
async function hedged<T>(call: () => Promise<T>): Promise<T> {
const first = call();
const backup = delay(P95_MS).then(() => call()); // p95'dan keyin ikkinchi urinish
return Promise.race([first, backup]); // qaysi biri OLDIN kelsa -> o'sha
}
// tail latency (p99)'ni keskin kamaytiradi; qo'shimcha yuk CHEGARALANGAN (faqat sekinlarga)
Hedged request qo‘shimcha yuk keltiradi — shuning uchun faqat p95’dan oshgan (kam sonli sekin) so‘rovlar uchun ishlatiladi va retry budget bilan cheklanadi. Aks holda yukni ikki barobar oshirasan. Bu — "The Tail at Scale" (Google) yondashuvi.
O‘lchamlash va backpressure
Little qonuni · backpressureCore’da bulkhead g‘oyasini ko‘rdik. Senior uni to‘g‘ri o‘lchaydi va backpressure bilan to‘ldiradi.
Bulkhead o‘lchamlash — Little qonuni
"Nechta bir vaqtli chaqiruvga ruxsat berish?" tasodifan tanlanmaydi. Little qonuni: concurrency = throughput × latency. Agar bog‘liqlik 100 req/s ni 50ms’da bajarsa — ~5 bir vaqtli slot yetadi. Buni bilib, semaphore o‘lchamini to‘g‘ri qo‘yasan:
// BULKHEAD (semaphore): har bog'liqlikka bir vaqtda ruxsat etilgan max chaqiruv
// O'LCHAM (Little's Law): concurrency = throughput * latency
// masalan 100 req/s * 0.05s = 5 -> ~5-10 slot yetarli
const paymentBulkhead = new Semaphore(10); // to'lovga bir vaqtda max 10 chaqiruv
const ok = await paymentBulkhead.tryAcquire(50 /*ms kut*/);
if (!ok) throw new BulkheadFullException(); // to'lgan -> DARHOL rad (fail fast)
try { return await this.payment.charge(); }
finally { paymentBulkhead.release(); }
Backpressure — "sekinlash" signali
Downstream sekinlashsa, upstream so‘rovlarni cheksiz buferlaydi — xotira to‘ladi, kechikish o‘sadi, oxiri OOM bilan qulaydi. Buferlash muammoni yashiradi, keyin portlatadi.
Cheksiz bufer o‘rniga — chegaralangan navbat; to‘lsa, upstream’ga "sekinlash" signali beriladi (yoki rad etiladi). Bu TCP oqim nazoratiga o‘xshaydi: qabul qiluvchi tayyor bo‘lganda yuboriladi. Reactive Streams (va RxJS) buni tabiiy qo‘llaydi. Prinsip: muammoni yashirma, tez signal ber.
Load shedding algoritmlari
CoDel · priority · brownoutCore’da "ortiqcha yukni rad et" dedik. Senior darajada qaysi so‘rovni, qachon rad etishni aqlli algoritm hal qiladi.
Oddiy rate limit yetarli emas
Qat’iy "sekundiga 1000 so‘rov" cheklovi qo‘pol: yuk past bo‘lsa ham keraksiz rad etadi, tizim allaqachon cho‘kayotgan bo‘lsa — kech qoladi. Aqlliroq yondashuvlar:
| Algoritm | G‘oya |
|---|---|
| Priority-based | Yuk oshsa — avval past prioritetli (analitika, batch) so‘rovlarni tashla, kritiklarini (to‘lov) saqla |
| Latency-based (CoDel) | Navbatda kutish vaqti oshsa — tashla (soni emas, kechikish signal). Tizim haqiqatan bosilganda reaksiya qiladi |
| LIFO under load | Bosim ostida — eng yangi so‘rovni birinchi xizmat qil (eskilari allaqachon timeout bo‘lgan bo‘lishi mumkin) |
| Adaptive (health-based) | Server sog‘lig‘iga (CPU, navbat) qarab qabul darajasini dinamik sozla |
Load shedding’ning maqsadi — "brownout": to‘liq qorong‘ilik (o‘lish) o‘rniga xira yorug‘lik (cheklangan, lekin ishlaydigan xizmat). Google/Facebook’ning yondashuvi: kechikish/navbatga qarab tashlash — chunki bu tizim haqiqatan bosilganini ko‘rsatadi, oddiy so‘rov soni emas.
Self-healing halqasi
outlier · autoscaleSelf-healing — tizim nosozlikni o‘zi aniqlab, tuzatadi (odam aralashuvisiz). Bu oldingi naqshlarni avtomatlashtirish halqasi.
Self-healing halqasi
Aniqla → izolyatsiya qil → tikla → qayta qo‘sh. Amalda bu oldingi mavzular birlashmasi:
- Health check (5-mavzu) — o‘lik/sog‘lom instance’ni aniqlaydi; liveness buzilsa — pod avtomatik qayta ishga tushadi.
- Outlier detection (5-mavzu Deep) — tinmay xato beradigan instance’ni trafikdan avtomatik chiqaradi, tuzalsa qaytaradi.
- Autoscaling (5-mavzu Deep) — yuk oshsa avtomatik ko‘proq instance.
- Circuit breaker (bu mavzu) — o‘layotgan bog‘liqlikni avtomatik uzadi va half-open bilan tuzalishini o‘zi sinaydi.
K8s bu halqaning ko‘p qismini beradi: liveness probe → restart, readiness probe → trafikdan chiqarish, HPA → autoscale. Ilova tomonda circuit breaker + retry + health endpoint qo‘shsang — to‘liq self-healing tizim.
Idempotency key va exactly-once
effectively-onceKurs davomida "idempotent bo‘lsin" dedik (3, 13-mavzular). Senior darajada — idempotency key mexanikasi va "exactly-once" afsonasi.
Idempotency key qanday ishlaydi
Mijoz har amalga noyob kalit yuboradi (masalan, Idempotency-Key header). Server: bu kalit ko‘rilganmi? Ha bo‘lsa — saqlangan natijani qaytar (qayta bajarmasdan); yo‘q bo‘lsa — bajar, natijani kalit bilan saqla:
// IDEMPOTENCY KEY: mijoz noyob kalit yuboradi; server dedup qiladi (retry xavfsiz)
async function handle(key: string, body: any) {
const existing = await this.store.get(key);
if (existing) return existing.result; // TAKROR -> saqlangan natijani qaytar
const locked = await this.store.acquireLock(key); // parallel takrorni to'sish (SETNX)
if (!locked) throw new ConflictException("In progress");
const result = await this.process(body); // FAQAT bir marta bajariladi
await this.store.save(key, result, { ttl: "24h" });
return result;
}
Ikki bir xil kalitli so‘rov bir vaqtda kelsa — ikkalasi "ko‘rilmagan" deb topib, ikki marta bajaradi. Yechim: kalit bo‘yicha qulf (Redis SETNX, 4-mavzu) — faqat bittasi bajaradi, ikkinchisi kutadi yoki natijani oladi.
Muhim haqiqat: tarmoqda chinakam "exactly-once delivery" imkonsiz (xabar yetdimi yoki ack yo‘qoldimi — bila olmaysan). Amalda erishiladigan narsa: at-least-once yetkazish + idempotent qayta ishlash = "effectively-once". Ya’ni xabar bir necha marta kelishi mumkin, lekin idempotency uni bir marta bajarilgandek qiladi. Bu — 3 va 13-mavzularning yakuniy tushunchasi.
Chaos engineering va senior cheklist
Resilience naqshlarini qurding — lekin ular haqiqatan ishlaydimi? Buni bilishning yagona yo‘li — chaos engineering: ataylab nosozlik keltirib, tizim chidashini tekshirish.
Chaos engineering amaliyoti
- Gipoteza: "To‘lov xizmati o‘lsa, buyurtma fallback bilan ishlashda davom etadi" — deb taxmin qil.
- Steady-state metrika: normal holatni o‘lchab ol (SLO, 12-mavzu).
- Nosozlik kirit: ataylab xizmatni o‘chir, kechikish qo‘sh, tarmoqni uz.
- Blast radius nazorati: avval kichik (bitta instance, oz trafik), ishonch ortsa kengaytir.
- Natija: gipoteza tasdiqlansa — yaxshi; buzilsa — zaiflik topildi, tuzatiladi (incidentdan oldin).
Netflix Chaos Monkey (tasodifan instance o‘chiradi) va Simian Army bu amaliyotni ommalashtirdi. Idea: nosozlik muqarrar bo‘lsa — uni nazorat ostida, ish vaqtida keltirib, tizimni doim chidamli tut. "Game day"larda jamoa birgalikda mashq qiladi.
Senior tayyorlik cheklisti
| Savol / amaliyot | Bo‘lim |
|---|---|
| Circuit breaker’ni sliding window, min-calls, slow-call bilan to‘g‘ri sozlayman | 1 |
| Adaptiv timeout va deadline propagation qo‘llayman (behuda ish yo‘q) | 2 |
| Retry budget bilan bo‘ronni to‘xtataman; tail uchun hedged request | 3 |
| Bulkhead’ni Little qonuni bilan o‘lchayman; backpressure bilan buferni cheklayman | 4 |
| Load shedding’ni prioritet/kechikish asosida qilaman (brownout) | 5 |
| Self-healing halqasini (health/outlier/autoscale/breaker) quraman | 6 |
| Idempotency key + qulf ishlataman; "effectively-once"ni tushunaman | 7 |
| Chaos engineering bilan resilience’ni sinab ko‘raman | 8 |
Bu 14-mavzuning Deep/Senior qatlami edi — Core bilan birga, Resilience Engineering endi to‘liq.
Endi oxirgi mavzu — “15-mavzu: Clean Architecture”. Bu butun kursni toza, saqlanadigan kod tuzilmasi bilan yakunlaydi: barcha o‘rganganingni qanday tashkil qilish. Core’dan boshlaymiz.