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.
Consistent/ring hash, maglev, P2C
ring hash · power of two choicesCore’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.
Sticky kerak (kesh/session affinity) → ring hash / maglev. Tekis yuk, sticky shart emas → P2C (least request) yoki round robin. EWMA (kechikishning ko‘chuvchi o‘rtachasi) bo‘yicha tanlash — eng aqlli, lekin murakkabroq.
TLS, HTTP/2 va ulanish nozikliklari
termination · passthrough · gRPCCore’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
| Yondashuv | Qanday | Kelishuv |
|---|---|---|
| TLS termination | LB TLS’ni ochadi, orqaga oddiy HTTP | Eng tez, sertifikat bir joyda; ichki tarmoq ishonchli bo‘lishi kerak |
| TLS passthrough | LB 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 yuboradi | End-to-end shifrlash + L7; sekinroq |
HTTP/2 va uzoq ulanishlar — yashirin tuzoq
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.
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).
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.
Envoy va Service Mesh
envoy · sidecar · istioYirik 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.
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.
Probe turlari va flapping sozlash
liveness/readiness/startupYomon 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
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.
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.
Connection draining va zero-downtime
drain · blue-green · canaryCore’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.
# 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
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.
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.
Autoscaling (HPA, cold start)
HPA · stabilization windowLoad 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
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.
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).
Pod autoscaler (HPA) — nusxa sonini oshiradi. Lekin node’larda joy tugasa — Cluster Autoscaler yangi server (node) qo‘shadi. Ikkalasi birga ishlaydi.
GeoDNS, Anycast, multi-region
anycast · geo failoverHozirgacha 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.
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).
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).
Metrikalar, retry bo‘roni, senior cheklist
retry budgetKuzatiladigan metrikalar
| Metrika | Nega muhim |
|---|---|
| Healthy host count | Nechta server tirik — keskin tushsa, incident |
| Per-upstream error rate / latency p99 | Qaysi server muammoli — outlier detection shunga tayanadi |
| Active connections / RPS | Yuk taqsimoti tekismi, hot server bormi |
| Ejection events | Serverlar chiqarilyaptimi (flapping belgisi) |
| Retry rate | Yuqori 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 / amaliyot | Bo‘lim |
|---|---|
| hash%N nega yomonligini bilaman; ring hash / maglev / P2C’ni o‘rinli tanlayman | 1 |
| HTTP/2 va gRPC uchun L7 kerakligini, TLS termination/passthrough farqini bilaman | 2 |
| Envoy outlier detection sozlayman; mesh qachon arzishini baholayman | 3 |
| Liveness/Readiness/Startup farqini bilaman; flapping’ni gisterezis bilan to‘xtataman | 4 |
| To‘g‘ri drain ketma-ketligi quraman; WebSocket draining va deploy strategiyalarini bilaman | 5 |
| HPA’ni biznes metrikasiga qo‘yaman; tez ko‘tar/sekin tushir; cold start’ni hal qilaman | 6 |
| GeoDNS/Anycast farqini, DNS failover sekinligini, multi-region ma’lumot muammosini bilaman | 7 |
| LB metrikalarini kuzataman; retry bo‘roni oldini retry budjeti bilan olaman | 8 |
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.