Tizim dizayni kursi · 5-mavzu · DEEP / SENIOR
TuzdiDinMuhammad

Load Balancing — Senior chuqurlik

Bu — 5-mavzuning 2-qatlami. Core darslikni o‘qib bo‘lgan deb hisoblanadi. Bu yerda eng ilg‘or narsalar: consistent/ring hash, P2C, Envoy va service mesh, health check flapping, connection draining, autoscaling va global LB/Anycast — junior’dan seniorgacha.

Daraja: SeniorMavzular: ring hash · Envoy/mesh · HPA · AnycastOld shart: 5-mavzu (Core)

Bu qatlamda nima bor

Core darslik asoslarni berdi. Bu Deep qatlam senior darajadagi chuqur mexanikani ochadi: ilg‘or LB algoritmlari, L4/L7 nozikliklari, Envoy va service mesh, health check flapping’ni sozlash, connection draining va deploy strategiyalari, autoscaling va global load balancing. Oxirida — senior tayyorlik cheklisti.

01
Deep · Algoritmlar

Consistent/ring hash, maglev, P2C

ring hash · power of two choices
🎛️

Core’da round robin va least connections ko‘rdik. Senior darajada esa katta klasterda bu algoritmlar yetmaydi — sticky taqsimot, minimal qayta-taqsimlash va arzon "eng kam band" tanlovi kerak bo‘ladi.

Nega oddiy hash(key) % N yomon

Sticky taqsimot uchun hash(key) % N ishlatsang, server qo‘shilsa/o‘chsa N o‘zgaradi va deyarli hamma kalit boshqa serverga ko‘chadi — sticky session/kesh ommaviy buziladi (4-mavzudagi consistent hashing aynan shu muammoning yechimi edi).

Consistent hashing + virtual nodes (ring hash)

Serverlar va kalitlar bitta "halqa"ga joylashtiriladi; kalit soat yo‘nalishidagi birinchi serverga tegishli. Server o‘zgarsa — faqat qo‘shni segment ko‘chadi, hammasi emas. Virtual node’lar (har serverning ko‘p nuqtasi) taqsimotni tekislaydi. Maglev — Google’ning tezroq, yanada tekis varianti.

# Envoy — consistent hashing (sticky) + tekis taqsimot uchun virtual node'lar
clusters:
- name: app
  lb_policy: RING_HASH            # yoki MAGLEV (Google'ning tez, tekis varianti)
  ring_hash_lb_config:
    minimum_ring_size: 1024       # ko'p virtual node -> notekislik kamayadi
  # hash nimaga qarab? masalan header yoki cookie -> bir user bir serverga

Power of Two Choices (P2C)

"Least connections" har so‘rovda butun ro‘yxatni tekshiradi (katta klasterda qimmat). P2C — 2 ta tasodifiy serverdan kam bandiga yuboradi: O(1), lekin natija deyarli optimal. Bu — yirik tizimlarning maxfiy retsepti:

// Power of Two Choices (P2C): butun ro'yxatni skanlamaymiz (O(N)) —
// 2 ta TASODIFIY server tanlab, kam bandiga yuboramiz. Natija deyarli optimal.
function pickP2C(servers) {
  const a = servers[rand(servers.length)];
  const b = servers[rand(servers.length)];
  return a.activeRequests <= b.activeRequests ? a : b;   // O(1), lekin tekis
}
// Envoy'da bu LEAST_REQUEST siyosatining ichida — katta klasterda
// "least connections"dan tez va arzon, "round robin"dan tekisroq.
Qaysi birini tanlash

Sticky kerak (kesh/session affinity) → ring hash / maglev. Tekis yuk, sticky shart emasP2C (least request) yoki round robin. EWMA (kechikishning ko‘chuvchi o‘rtachasi) bo‘yicha tanlash — eng aqlli, lekin murakkabroq.

02
Deep · L4/L7

TLS, HTTP/2 va ulanish nozikliklari

termination · passthrough · gRPC
🔬

Core’da L4/L7 farqini ko‘rdik. Senior darajada bu farq TLS, ulanishlar va HTTP/2 bilan chuqurlashadi — va noto‘g‘ri tanlov yashirin muammolar keltiradi.

TLS bilan 3 yondashuv

YondashuvQandayKelishuv
TLS terminationLB TLS’ni ochadi, orqaga oddiy HTTPEng tez, sertifikat bir joyda; ichki tarmoq ishonchli bo‘lishi kerak
TLS passthroughLB shifrlangan trafikni o‘zgartirmasdan uzatadi (L4)To‘liq maxfiylik (LB ham ko‘rmaydi); lekin L7 marshrut yo‘q
Re-encryption (mTLS)LB ochadi, qayta shifrlab orqaga yuboradiEnd-to-end shifrlash + L7; sekinroq

HTTP/2 va uzoq ulanishlar — yashirin tuzoq

Muammo

HTTP/2 bitta uzoq ulanishda ko‘p so‘rov (stream) yuboradi. Agar L4 balanser ishlatsang, u ulanish darajasida taqsimlaydi — bitta client’ning barcha so‘rovlari bitta serverga "yopishib" qoladi, yuk notekis bo‘ladi. Bu gRPC’da (doimo HTTP/2) ayniqsa og‘riqli.

Yechim

HTTP/2 va gRPC uchun L7 balanser ishlat — u har so‘rov (stream) darajasida taqsimlaydi, ulanish emas. Envoy/ALB buni qiladi. Yoki client-side LB (gRPC + service discovery).

Source IP

L4 odatda manba IP’ni saqlaydi. L7 (termination) esa o‘z IP’sidan ko‘rinadi — shuning uchun X-Forwarded-For (yoki PROXY protocol) kerak. Buni unutsang — rate limiting va audit log noto‘g‘ri ishlaydi.

03
Deep · Proxy

Envoy va Service Mesh

envoy · sidecar · istio
🕸️

Yirik mikroservis tizimlarda balanser shunchaki "oldidagi quti" emas — u Envoy kabi aqlli proksi yoki butun service mesh bo‘ladi.

Envoy — zamonaviy L7 proksi

Envoy oddiy balanserdan ko‘ra ko‘proq narsa beradi: dinamik konfiguratsiya (xDS API orqali jonli yangilanadi), ilg‘or LB (ring hash, maglev, P2C), retry, circuit breaking, outlier detection (14-mavzu) va boy kuzatuvchanlik — hammasi bitta joyda. Aktiv + passiv health birga:

# Envoy — passiv health (outlier detection) + aktiv health birga
clusters:
- name: app
  outlier_detection:            # PASSIV: real trafikdagi xatolarni kuzatadi
    consecutive_5xx: 5          # 5 ta ketma-ket 5xx -> serverni chiqar
    interval: 10s
    base_ejection_time: 30s     # 30s chetlatadi, keyin qaytaradi
    max_ejection_percent: 50    # bir vaqtda 50%dan ko'p chiqarmaydi (himoya)
  health_checks:                # AKTIV: probe yuborib turadi
  - timeout: 2s
    interval: 5s
    unhealthy_threshold: 3
    healthy_threshold: 2
    http_health_check: { path: /health }

Service Mesh — LB’ni har xizmatga ko‘chirish

Service mesh (Istio, Linkerd) har bir xizmat yoniga sidecar proksi (Envoy) qo‘yadi. Endi xizmatlararo butun trafik shu sidecar’lar orqali o‘tadi:

  • Data plane — sidecar’lar (haqiqiy trafikni tashiydi): LB, retry, mTLS, metrika.
  • Control plane — markaziy miya (Istiod): siyosatlarni hamma sidecar’ga tarqatadi.
Pod A App Sidecar Pod B App Sidecar mTLS Control plane (Istiod)siyosat -> sidecar'larga
Service mesh: data plane (sidecar’lar) + control plane (markaziy miya)
Qachon mesh kerak (va kerak emas)

Mesh — mTLS, yagona siyosat, kuzatuvchanlik va trafik boshqaruvini kod o‘zgartirmasdan beradi. Lekin u jiddiy murakkablik va resurs qo‘shadi (har podda qo‘shimcha proksi). O‘nlab mikroservis va ko‘p jamoa bo‘lsa — arziydi. Bir nechta xizmat uchun — ortiqcha; oddiy LB + kutubxona yetadi.

04
Deep · Health

Probe turlari va flapping sozlash

liveness/readiness/startup
📟

Yomon sozlangan health check — soppa-sog‘ serverni "o‘lik" deb chiqarib, keyin qaytarib, yana chiqaradi (flapping). Bu tizimni barqarorlashtirish o‘rniga beqaror qiladi.

Liveness vs Readiness vs Startup — eng muhim farq

Ko‘pchilik buni chalkashtiradi, natijada deploy va incidentlar yomonlashadi:

  • Readiness — "men hozir trafik qabul qila olamanmi?". Xato → LB trafik yubormaydi, lekin pod o‘chmaydi (masalan, baza vaqtincha sekin).
  • Liveness — "men tirikmanmi?". Xato → pod qayta ishga tushiriladi (deadlock, osilib qolish).
  • Startup — sekin ishga tushadigan ilova uchun: tugaguncha liveness’ni kutdiradi (aks holda sekin start "o‘lik" deb qayta-qayta o‘chiriladi).
# Kubernetes — UCHTA probe bir-biridan farq qiladi (eng ko'p chalkashtiriladi)
readinessProbe:                 # "traffik qabul qila olamanmi?" -> LB shu asosida yuboradi
  httpGet: { path: /health/ready, port: 3000 }
  periodSeconds: 5
  failureThreshold: 3           # 3 marta xato -> LB'dan chiqar (lekin O'CHIRMA)
  successThreshold: 1
livenessProbe:                  # "tirikmanmi?" -> buzilsa podni QAYTA ISHGA TUSHIR
  httpGet: { path: /health/live, port: 3000 }
  periodSeconds: 10
  failureThreshold: 3
startupProbe:                   # sekin start uchun: tugaguncha liveness kutadi
  httpGet: { path: /health/live, port: 3000 }
  failureThreshold: 30          # 30 * periodSeconds gacha startga ruxsat

Flapping’ni qanday to‘xtatish

Sabablar

1. Threshold juda sezgir (1 ta xato → darhol chiqarish).
2. Health check juda chuqur: ikkilamchi bog‘liqlik (masalan, analitika xizmati) o‘lsa, asosiy server ham "o‘lik" deb belgilanadi — kaskadli health failure.
3. Probe’lar bir vaqtda urilib, vaqtinchalik tebranishni nosozlik deb o‘qiydi.

Yechimlar

Gisterezis: unhealthy_threshold > 1 va healthy_threshold > 1 (bir necha marta tasdiqlansin). To‘g‘ri chuqurlik: health faqat kritik bog‘liqlikni tekshirsin (ikkilamchisi o‘lsa, "degraded" bo‘l, lekin "down" emas). Slow start / warm-up: yangi serverga trafikni asta-sekin ko‘paytirish (birato‘la zarba bermaslik). Jitter interval’larga.

05
Deep · Deploy

Connection draining va zero-downtime

drain · blue-green · canary
🚰

Core’da graceful shutdown’ni eslatib o‘tdik. Senior darajada bu aniq ketma-ketlik va uzoq ulanishlar (WebSocket) bilan murakkablashadi — noto‘g‘ri qilsang, har deploy’da so‘rovlar yo‘qoladi.

To‘g‘ri drain ketma-ketligi

Server birdan o‘chmaydi — u "drain" bo‘ladi: yangi trafikni to‘xtatib, ishdagilarni tugatadi.

1. readiness=failLB chiqaradi 2. yangi so‘rov yo‘qishdagilar tugaydi 3. ulanishlar yopiladi 4. SIGTERM → chiqish
Drain: avval LB’dan chiqar → ishdagini tugat → keyin o‘ch
# Uzilishsiz deploy — to'g'ri o'chirish KETMA-KETLIGI
lifecycle:
  preStop:
    exec:
      command: ["sh","-c","sleep 15"]   # 1) LB endpoint'lardan chiqishimni kut
terminationGracePeriodSeconds: 45        # 2) ishdagi so'rovlarga drain vaqti

# Ilovada (NestJS): SIGTERM kelganda
//  a) readiness'ni "unhealthy" qil  -> LB yangi so'rov yubormaydi
//  b) ishdagi so'rovlarni tugat (yangi ulanish qabul qilma)
//  c) DB/Redis/broker ulanishlarini toza yop
//  d) keyin chiqish
Uzoq ulanishlar (WebSocket) — alohida og‘riq

HTTP so‘rovi soniyalarda tugaydi, lekin WebSocket soatlab ochiq turadi — drain timeout’ida tugamaydi. Yechimlar: maksimal ulanish umri (connection max lifetime) belgilash; deploy’da client’ga "qayta ulan" signali yuborish; ulanishlarni asta-sekin yangi serverlarga ko‘chirish.

Deploy strategiyalari — LB shularni mumkin qiladi

Rolling: serverlarni birma-bir yangilash (drain bilan). Blue-green: to‘liq yangi muhit ("green") tayyorlab, LB’ni birdan unga o‘tkazish (orqaga qaytarish oson). Canary: trafikning kichik %ini yangi versiyaga yo‘naltirib, kuzatib, asta oshirish.

06
Deep · Scaling

Autoscaling (HPA, cold start)

HPA · stabilization window
📈

Load balancing serverlarni taqsimlaydi; autoscaling esa ularning sonini yukka qarab avtomatik o‘zgartiradi. Ikkalasi birga — chinakam elastik tizim.

Nimaga qarab masshtablash

CPU/RAM — eng oddiy, lekin ko‘pincha noto‘g‘ri signal (I/O-bound ilovada CPU past bo‘lib, baribir sekin bo‘lishi mumkin). Yaxshiroq: biznes metrikalari — RPS, navbat uzunligi, p95 kechikish:

# Horizontal Pod Autoscaler — yukka qarab nusxa sonini avtomatik o'zgartiradi
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
  minReplicas: 3
  maxReplicas: 30
  metrics:
  - type: Resource
    resource: { name: cpu, target: { type: Utilization, averageUtilization: 65 } }
  - type: Pods                       # maxsus metrika: RPS bo'yicha
    pods:
      metric: { name: http_requests_per_second }
      target: { type: AverageValue, averageValue: "500" }
  behavior:
    scaleUp:   { stabilizationWindowSeconds: 30 }    # TEZ ko'tar (yuk kelsa)
    scaleDown: { stabilizationWindowSeconds: 300 }   # SEKIN tushir (thrashing yo'q)

Asosiy prinsip — tez ko‘tar, sekin tushir

Nega assimetrik

Yuk kelsa tez ko‘tarish kerak (foydalanuvchi kutmasin). Lekin yuk tushganda darhol kamaytirsang — keyingi to‘lqinda yana ko‘tarasan, bu thrashing (tinmay ko‘tarib-tushirish) va beqarorlik. Shuning uchun scaleDown’ga uzun stabilization window qo‘yiladi.

Cold start + slow start tuzog‘i

Autoscaler yangi pod qo‘shdi, lekin u hali "isimagan" (JIT, kesh bo‘sh, ulanish pool to‘lmagan). LB unga birato‘la to‘liq trafik bersa — yangi pod cho‘kadi. Yechim: slow start (trafikni asta oshirish) + startup probe + LB yangi instance’ni tez topishi (service discovery integratsiyasi).

Ikki qatlam

Pod autoscaler (HPA) — nusxa sonini oshiradi. Lekin node’larda joy tugasa — Cluster Autoscaler yangi server (node) qo‘shadi. Ikkalasi birga ishlaydi.

07
Deep · Global

GeoDNS, Anycast, multi-region

anycast · geo failover
🌍

Hozirgacha bitta DC ichidagi balansni ko‘rdik. Foydalanuvchilar dunyo bo‘ylab bo‘lsa — trafikni eng yaqin mintaqaga yo‘naltirish va butun mintaqa o‘lsa failover qilish kerak.

GeoDNS va latency-based routing

DNS darajasida: foydalanuvchining joylashuvi (yoki o‘lchangan kechikish) bo‘yicha eng yaqin mintaqaning IP’sini qaytarish (masalan AWS Route 53). Bundan tashqari weighted (kanareyka uchun) va failover (mintaqa o‘lsa zaxiraga) routing.

Anycast — bitta IP, ko‘p joy

Bitta IP manzil bir necha mintaqadan BGP orqali e’lon qilinadi; tarmoq foydalanuvchini eng yaqin nuqtaga yo‘naltiradi. CDN va DNS provayderlari shunday ishlaydi — DNS keshiga bog‘liq emas, juda tez.

User (EU) User (Asia) 1.2.3.4 (anycast) EU mintaqa Asia mintaqa
Bir IP — har user eng yaqin mintaqaga (anycast/BGP)
DNS failover’ning sekinligi

DNS-based failover TTLga bog‘liq: client eski IP’ni keshlab turadi, shuning uchun mintaqa o‘lganda yangi IP’ga o‘tish daqiqalar olishi mumkin. Past TTL yordam beradi, lekin DNS yukini oshiradi. Anycast bu muammodan xoli (BGP marshrutni qayta hisoblaydi).

Multi-region = ma’lumot muammosi

Trafikni mintaqalarga bo‘lish oson; ma’lumotni mintaqalararo izchil saqlash — qiyin (kechikish, CAP — 11-mavzu). Ko‘pincha "har mintaqa o‘z ma’lumotiga yaqin" yoki "bitta yozuv mintaqasi + o‘qish replikalari" naqshlari ishlatiladi (7-mavzu: replikatsiya).

08
Deep · Operations

Metrikalar, retry bo‘roni, senior cheklist

retry budget

Kuzatiladigan metrikalar

MetrikaNega muhim
Healthy host countNechta server tirik — keskin tushsa, incident
Per-upstream error rate / latency p99Qaysi server muammoli — outlier detection shunga tayanadi
Active connections / RPSYuk taqsimoti tekismi, hot server bormi
Ejection eventsServerlar chiqarilyaptimi (flapping belgisi)
Retry rateYuqori bo‘lsa — retry bo‘roni xavfi

Retry bo‘roni (retry storm) — senior tuzog‘i

Serverlar sekinlashdi → hamma retry qildi → yuk 2-3 barobar oshdi → butun klaster yiqildi. Yechim — retry budjeti va circuit breaking (14-mavzu):

# Retry "bo'roni"ning oldini olish — retry budjeti (Envoy)
retry_policy:
  retry_on: "5xx,reset,connect-failure"
  num_retries: 2
  retry_budget:
    budget_percent: { value: 20 }     # retry'lar umumiy trafikning 20%idan oshmasin
# Aks holda: serverlar sekinlashdi -> hamma retry qiladi -> yuk 3x -> butun klaster yiqiladi

Senior tayyorlik cheklisti

Savol / amaliyotBo‘lim
hash%N nega yomonligini bilaman; ring hash / maglev / P2C’ni o‘rinli tanlayman1
HTTP/2 va gRPC uchun L7 kerakligini, TLS termination/passthrough farqini bilaman2
Envoy outlier detection sozlayman; mesh qachon arzishini baholayman3
Liveness/Readiness/Startup farqini bilaman; flapping’ni gisterezis bilan to‘xtataman4
To‘g‘ri drain ketma-ketligi quraman; WebSocket draining va deploy strategiyalarini bilaman5
HPA’ni biznes metrikasiga qo‘yaman; tez ko‘tar/sekin tushir; cold start’ni hal qilaman6
GeoDNS/Anycast farqini, DNS failover sekinligini, multi-region ma’lumot muammosini bilaman7
LB metrikalarini kuzataman; retry bo‘roni oldini retry budjeti bilan olaman8

Bu 5-mavzuning Deep/Senior qatlami edi — Core bilan birga, load balancing endi junior’dan senior gacha to‘liq.

Keyingi mavzu: “6-mavzu: Database Sharding” — ma’lumotlar bazasini masshtablash. Core’dan boshlaymiz.