IlmHamroh
Dasturlash kitobi (eski nashr)/9-QISM — Arxitektura6/10-dars35 daqiqa
Mundarija (48)

Mikroservislar aloqasi — REST, gRPC, RabbitMQ va Kafka (9.6-bob)

9-QISM — Arxitektura va ilg'or backend · 6-mavzu


1. Kirish va motivatsiya

Mikroservis (yoki modular monolith modullari) qarorini bildik 9.5-bob. Endi eng muhim amaliy savol: ular qanday gaplashadi? Monolitda modullar funksiya chaqiruvi orqali (oddiy, tez, ishonchli — 9.5: 2.1); lekin mikroservislar tarmoq orqali (boshqa jarayon, boshqa server). Bu — mikroservis arxitekturasining yuragi: noto'g'ri aloqa usuli — sekin, ishonchsiz, qattiq bog'liq tizim (distributed monolith — 9.5: 2.8); to'g'ri tanlov — tez, chidamli, mustaqil. Uch asosiy usul bor: REST, gRPC, message queues (RabbitMQ/Kafka).

8.16'da bularni qisman ko'rdik (NestJS transport); endi har birini chuqur — qachon qaysi, kuchli/zaif tomonlari, real ishlatilishi — o'rganamiz. Asosiy farq: sinxron (REST/gRPC — so'rov yuborib javob kutadi — darrov, lekin bog'liq) vs asinxron (message queue — event yuborib kutmaydi — bo'shashgan, chidamli, lekin eventual). Bu tanlov — tizimingiz tezligi, ishonchliligi, masshtabini belgilaydi. Senior dasturchi har birini biladi va to'g'ri ishlatadi.

Bu bob: aloqa turlari (sinxron vs asinxron — chuqur), REST (oddiy, universal, over/under-fetching), gRPC (tez, tipli, protobuf, HTTP/2, 4 streaming turi), message queue (RabbitMQ — exchange/routing/prefetch/DLQ, Kafka — log/partition/offset/replay, Redis Streams), message patternlar (request/reply, pub/sub, competing consumers, fan-out), delivery kafolati (at-most/at-least/exactly-once), ordering va backpressure, circuit breaker/bulkhead/timeout/retry (resilience), correlation ID, service mesh (sidecar/Istio), schema evolution (proto/Avro), va hybrid (qaysi joyda qaysi + tanlov jadvali). Bu bob 8.16 (transport), 9.5 (arxitektura), 9.7 (event-driven), 5.7 (REST), 17-bob (GraphQL) bilan bog'liq. Aloqa usuli — taqsimlangan tizimning ishonchliligi asosi.

O'xshatish: xizmatlararo aloqa — odamlar orasidagi muloqot usullari. REST — telefon qo'ng'irog'i (sinxron — qo'ng'iroq qilasiz, javob kutasiz; oddiy, universal, lekin u band/o'chiq bo'lsa kutib qolasiz). gRPC — ichki selektor/ratsiya (sinxron, lekin tez, qisqa kod bilan — jamoa ichida; tashqi odam tushunmaydi). Message queue — xat/pochta qutisi (asinxron — xat tashlab ketasiz, qabul qiluvchi keyin o'qiydi; u band/yo'q bo'lsa ham xat saqlanadi — chidamli). Yaxshi muloqotchi (senior) qaysi vaziyatda qaysi usulni ishlatishni biladi: shoshilinch javob → qo'ng'iroq; "bilib qo'ying" → xat.

Nega muhim?

  • Mikroservis yuragi — xizmatlar qanday gaplashadi.
  • Tezlik/ishonchlilik — to'g'ri usul = chidamli tizim.
  • Sinxron vs asinxron — eng muhim tanlov (bog'liqlik).
  • Senior bilim — REST/gRPC/queue (qachon qaysi).

2. Nazariya — chuqur tushuntirish

2.1. Sinxron vs asinxron (asosiy farq)

text
  SINXRON (so'rov-javob — kutadi):
  Xizmat A → so'rov → Xizmat B → javob → A davom etadi
  ✓ Darrov javob (ma'lumot kerak); oddiy mantiq
  ✗ A, B'ga bog'liq (B yiqilsa/sekinlasa → A ham); latency zanjiri
  → REST, gRPC

  ASINXRON (event/xabar — kutmaydi):
  Xizmat A → event → [QUEUE] → Xizmat B keyin oladi
  ✓ Bo'shashgan (A, B'ni kutmaydi); chidamli (B yiqilsa, xabar navbatda)
  ✓ Masshtab (navbat buferlaydi); ko'p tinglovchi
  ✗ Eventual consistency (darrov emas); murakkab kuzatuv
  → RabbitMQ, Kafka

Sinxron vs asinxron (eng muhim farq): sinxron (REST/gRPC — so'rov yuborib javob kutadi — darrov ma'lumot, lekin B'ga bog'liq: B yiqilsa A ham, latency zanjiri); asinxron (message queue — event yuborib kutmaydi — bo'shashgan, chidamli: B yiqilsa xabar navbatda, masshtab). Tanlov: javob darrov kerakmi? (ha → sinxron; yo'q/fon ish → asinxron). Asinxron — chidamliroq (bog'liqlik kam — 9.5: 2.11). Bu — aloqa qarorining asosi.

2.2. REST (oddiy, universal)

text
  REST 5.7-bob — HTTP + JSON (eng keng):
  Xizmat A → HTTP GET/POST → Xizmat B → JSON javob

  ✓ Oddiy, universal (har til/platforma tushunadi)
  ✓ Inson o'qiy oladi (JSON, brauzer test)
  ✓ Keng vositalar (Postman, curl, Swagger — 8.8)
  ✗ Sekinroq (JSON parse, HTTP overhead, matn)
  ✗ Shartnoma qat'iy emas (JSON — tip yo'q)
  ✗ Qattiq bog'liq (sinxron — 2.1)

  → Public API (tashqi), oddiy CRUD, brauzer/mobil mijoz

REST (5.7 — HTTP+JSON): eng keng, universal (har til tushunadi), inson o'qiy oladi (JSON), keng vositalar (Postman/Swagger). Kamchilik: sekinroq (JSON parse, HTTP overhead), shartnoma qat'iy emas (tip yo'q — runtime xato), qattiq bog'liq (sinxron). Qachon: public API (tashqi developerlar), oddiy CRUD, brauzer/mobil mijoz (REST universal). Tashqi dunyo bilan — REST (gRPC tashqarida noqulay). Ichki tez aloqa uchun — gRPC afzal 2.3-bob.

Over-fetching va under-fetching (REST'ning strukturaviy kamchiligi). REST'da endpoint javob shaklini serverda qattiq belgilaydi — mijoz ehtiyoji bilan mos kelmasligi mumkin:

text
  OVER-FETCHING (keragidan ko'p):
  GET /users/42  →  { id, ism, email, manzil, telefon, avatar,
                      tug'ilgan_sana, ro'yxatdan_o'tgan, ... }
  Lekin mijozga faqat "ism" kerak edi → ortiqcha bayt (tarmoq, batareya)

  UNDER-FETCHING (kam — N+1 so'rov):
  GET /users/42          → { id, ism, orderIds: [1,2,3] }
  GET /orders/1          → ...            ┐
  GET /orders/2          → ...            ├─ har bog'liq ma'lumot uchun
  GET /orders/3          → ...            ┘  alohida so'rov (roundtrip zanjiri)

  → Bir ekran uchun 4 ta HTTP so'rov (sekin, ayniqsa mobil)

Over/under-fetching — REST'ning tug'ma muammosi: endpoint javob shakli qattiq, mijoz ehtiyoji bilan mos kelmaydi. Over-fetching — keragidan ko'p maydon keladi (ortiqcha tarmoq); under-fetching — bir ekran uchun bir nechta so'rov (roundtrip zanjiri, mobilda sezilarli). Bu — aynan GraphQL hal qiladigan muammo (mijoz kerakli maydonlarni so'raydi — 17-bob). REST'da yumshatish: maxsus endpoint (/users/42/summary), ?fields= filtri, yoki BFF (Backend-for-Frontend — 9.8). Ichki xizmatlararo aloqada esa bu muammo gRPC'da kamroq (aniq shartnoma, binary — 2.3).

2.3. gRPC (tez, tipli, protobuf)

text
  gRPC — Google'ning RPC protokoli (ichki xizmatlar uchun):
  - Protobuf (binary — JSON'dan kichik/tez); HTTP/2 (multiplexing)
  - Strong contract (.proto fayl — tip xavfsiz)
  - 4 turdagi: unary, server-stream, client-stream, bi-directional stream

  ✓ TEZ (binary, HTTP/2 — REST'dan 5-10x tez)
  ✓ Tipli shartnoma (.proto — kod generatsiya — tip xavfsiz)
  ✓ Streaming (real-time — bi-directional)
  ✗ Inson o'qiy olmaydi (binary); brauzer to'g'ridan qo'llamaydi
  ✗ Murakkabroq (proto, kod generatsiya)

  → Ichki mikroservislar (xizmatlararo), tez/ko'p so'rov, streaming

gRPC (Google RPC — ichki xizmatlar): Protobuf (binary — JSON'dan kichik/tez) + HTTP/2 (multiplexing) + strong contract (.proto fayl — tip xavfsiz, kod generatsiya). 4 tur: unary (oddiy), server/client/bi-directional stream. 5-10x tez REST'dan (binary). Kamchilik: inson o'qiy olmaydi (binary), brauzer to'g'ridan qo'llamaydi (gRPC-Web kerak), murakkabroq. Qachon: ichki mikroservislar (xizmatlararo — tez, ko'p so'rov), streaming (real-time). Tashqi — REST; ichki — gRPC.

HTTP/2 nega tez (gRPC poydevori). REST odatda HTTP/1.1 ustida: har so'rov alohida ulanish yoki ketma-ketlik (head-of-line blocking), sarlavhalar matn ko'rinishida takrorlanadi. gRPC esa HTTP/2 talab qiladi:

text
  HTTP/1.1 (REST):                 HTTP/2 (gRPC):
  - Matn sarlavha (takror)         - Binary framing (ixcham)
  - 1 so'rov / ulanish (ketma-ket) - Multiplexing (1 ulanishda ko'p oqim parallel)
  - Sarlavha har safar to'liq      - HPACK (sarlavha siqish)
  - Faqat so'rov-javob             - Server push, bi-directional stream

  → gRPC: 1 TCP ulanish + protobuf (binary) → kam latency, ko'p parallel

gRPC'ning 4 chaqiruv turi (streaming to'liq). .protoda stream kalit so'zi so'rov/javobga qo'yiladi va 4 kombinatsiya beradi:

text
  1) UNARY (oddiy so'rov-javob):
     rpc GetUser (Req) returns (Res);
     Klient ──1 so'rov──→ Server ──1 javob──→ Klient
     → oddiy CRUD, REST'ga o'xshash (lekin binary/tez)

  2) SERVER STREAMING (bir so'rov, ko'p javob):
     rpc WatchPrice (Req) returns (stream Res);
     Klient ──1 so'rov──→ Server ══javob oqimi══→ Klient (ko'p)
     → jonli narx, feed, katta ro'yxatni bo'lib yuborish (pagination o'rniga)

  3) CLIENT STREAMING (ko'p so'rov, bir javob):
     rpc Upload (stream Chunk) returns (Res);
     Klient ══so'rov oqimi══→ Server ──1 javob──→ Klient
     → fayl/telemetriya yuklash (bo'laklab), yig'indi hisoblash

  4) BI-DIRECTIONAL STREAMING (ikki tomon oqim, mustaqil):
     rpc Chat (stream Msg) returns (stream Msg);
     Klient ══oqim══⇄══oqim══ Server (bir vaqtda ikki yo'nalish)
     → chat, o'yin, real-time hamkorlik (WebSocket o'rniga, ichki)

gRPC 4 turi: unary (1 so'rov → 1 javob — oddiy); server streaming (1 so'rov → javob oqimi — jonli narx, feed); client streaming (so'rov oqimi → 1 javob — fayl/telemetriya yuklash); bi-directional (ikki tomon mustaqil oqim — chat, o'yin). Bu — HTTP/2 multiplexing sabab mumkin (bir ulanishda ikki yo'nalish). REST bunga qodir emas (streaming cheklangan — SSE/WebSocket alohida). Qachon streaming: ko'p/uzluksiz ma'lumot (real-time, katta ro'yxat, telemetriya). Oddiy so'rov uchun unary yetarli (streaming ortiqcha murakkablik). NestJS'da unary → @GrpcMethod, streaming → @GrpcStreamMethod (Misol 4).

2.4. Protobuf va .proto (gRPC shartnomasi)

protobuf
// user.proto — gRPC shartnoma (tip xavfsiz, til-agnostik)
syntax = "proto3";

service UserService {
  rpc GetUser (GetUserRequest) returns (User);        // unary (oddiy)
  rpc ListUsers (Empty) returns (stream User);        // server-stream
}

message GetUserRequest {
  string id = 1;                                       // maydon raqami (binary tartib)
}
message User {
  string id = 1;
  string ism = 2;
  string email = 3;
}
// → .proto'dan kod generatsiya (TS/Go/Python — har til) — tip xavfsiz shartnoma

Protobuf/.proto (gRPC shartnomasi): .proto fayl — xizmat va xabarlarni til-agnostik belgilaydi (TS, Go, Python — har til). service (RPC metodlar), message (ma'lumot — maydon raqami bilan — binary tartib). .protodan kod generatsiya (klient + server tiplari — tip xavfsiz, qo'lda yozilmaydi). Shartnoma markazda (REST'dagi JSON'dan farqli — qat'iy). Bu — gRPC'ning kuchi (ishonchli shartnoma). Versiyalashda diqqat (maydon raqami o'zgartirmaslik).

2.5. Message Queue (asinxron — RabbitMQ)

text
  MESSAGE QUEUE — asinxron, ishonchli yetkazish (8.16: 2.6):
  Producer → [QUEUE] → Consumer (keyin oladi)

  RabbitMQ — an'anaviy navbat (task queue):
  - Routing (exchange — qaysi navbatga)
  - Ack/nack (ishonchli — tasdiqlash)
  - Dead-letter (xato → DLQ — 8.20: 2.9)
  - Retry, delayed delivery
  → Vazifa qayta ishlash (email, video, hisobot — fon ish)

  ✓ Bo'shashgan, chidamli (consumer yiqilsa, xabar navbatda)
  ✓ Yuk balansi (ko'p consumer — bittadan oladi)

Message Queue (asinxron — 8.16: 2.6): producer → navbat → consumer (keyin oladi). RabbitMQ (an'anaviy task queue): routing (exchange), ack/nack (ishonchli tasdiqlash), dead-letter (8.20: 2.9), retry, delayed. Qachon: vazifa qayta ishlash (email, video, hisobot — fon — 8.22), yuk balansi (ko'p consumer bittadan oladi). Bo'shashgan, chidamli (consumer yiqilsa xabar navbatda — yo'qolmaydi). RabbitMQ — "ishni bajaring" (task); Kafka — "voqea bo'ldi" (event — 2.6).

RabbitMQ modeli: exchange, queue, binding, routing key. RabbitMQ'ning kuchi — producer navbatga to'g'ridan yozmasligi. U exchangega yozadi, exchange esa binding qoidalari asosida xabarni qaysi navbat(lar)ga yo'naltirishni hal qiladi (AMQP protokoli):

text
  Producer ──xabar (routing key bilan)──→ EXCHANGE
                                             │  binding qoidalari
                    ┌────────────────────────┼────────────────────┐
                    ▼                         ▼                    ▼
                 Queue A                   Queue B              Queue C
                    │                         │                    │
                 Consumer                  Consumer             Consumer

  - Exchange: yo'naltiruvchi (navbatni bilmaydi, faqat qoida)
  - Queue: xabar saqlanadigan navbat
  - Binding: exchange↔queue bog'lanishi (routing pattern bilan)
  - Routing key: producer xabarga qo'yadigan "manzil" yorlig'i

Exchange turlari (4 xil yo'naltirish). Aynan shu tanlov RabbitMQ'da xabar kimga borishini belgilaydi:

text
  DIRECT  — routing key TO'LIQ mos kelsa (aniq manzil)
            key="payment.failed" → shu bindingli navbatga
            → aniq vazifa turi bo'yicha yo'naltirish

  TOPIC   — routing key PATTERN bilan (* = 1 so'z, # = ko'p so'z)
            binding="order.*.eu"  ← "order.created.eu" mos, "order.created.us" yo'q
            → moslashuvchan, ko'p o'lchovli yo'naltirish (eng ko'p ishlatiladi)

  FANOUT  — routing key'ga QARAMAY hamma bog'langan navbatga (broadcast)
            → bir event → hamma qiziqqan xizmat (pub/sub — 2.6d)

  HEADERS — routing key o'rniga xabar SARLAVHALARI bo'yicha moslash
            → murakkab, kamdan-kam (ko'p atribut bo'yicha filtrlash)

Prefetch (QoS — adolatli taqsimot). Kelishuvsiz, RabbitMQ consumerga hamma xabarni birdan itaradi — bir sekin consumer navbatni "yutib" olishi mumkin. prefetch (QoS) — consumer bir vaqtda nechta tasdiqlanmagan xabar ololishini cheklaydi:

text
  prefetch=1 : consumer 1 xabarni ishlaydi, ack bergach keyingisi
               → adolatli (tez consumer ko'proq oladi — round-robin emas)
  prefetch=N : bir vaqtda N ta (yuqori throughput, lekin kamroq adolat)

  ❗ Og'ir/uzoq vazifalar → kichik prefetch (adolat); yengil → kattaroq (tezlik)

Ack/nack va DLQ (ishonchli yetkazish). Consumer xabarni olgach ack (bajarildi — navbatdan o'chir) yoki nack (xato) yuboradi. ack kelmasa (consumer yiqildi), RabbitMQ xabarni boshqa consumerga qayta beradi (yo'qolmaydi):

text
  Xabar → Consumer ──ack──→ o'chadi (muvaffaqiyat)
                   ──nack (requeue=true)──→ navbatga qaytadi (qayta urinish)
                   ──nack (requeue=false)──→ Dead-Letter Exchange → DLQ

  DLQ (Dead-Letter Queue): qayta-qayta xato beradigan "zaharli" xabar (poison message)
  → asosiy navbatni bloklamaydi; keyin qo'lda/alohida tekshiriladi (8.20: 2.9)
  → retry chegarasi (masalan 3 marta) → DLQ (cheksiz aylanmaslik uchun)

RabbitMQ chuqur: producer exchangega yozadi (navbatga emas), exchange binding + routing key bo'yicha navbatga yo'naltiradi. 4 exchange turi: direct (aniq key mos), topic (*/# pattern — eng moslashuvchan), fanout (broadcast — hammaga), headers (sarlavha bo'yicha). Prefetch (QoS) — consumer bir vaqtda nechta ishlashi (kichik → adolat, katta → throughput). Ack/nack — muvaffaqiyat tasdig'i (kelmasa qayta beriladi — yo'qolmaydi); nack(requeue=false) yoki retry chegarasi → DLQ (zaharli xabar asosiy navbatni bloklamaydi — 8.20: 2.9). Bu — RabbitMQ'ni Kafka'dan ajratadigan boy routing (Kafka'da bunday emas — 2.6).

2.6. Kafka (event streaming)

text
  KAFKA — event streaming platforma (RabbitMQ'dan farqli):
  - Event LOG (o'chmaydi — saqlanadi, qayta o'qiladi — replay)
  - Topic + partition (parallel, tartib partition ichida)
  - Ko'p consumer guruh (har biri butun stream'ni o'qiydi)
  - Juda yuqori throughput (millionlab event/sek)

  RabbitMQ vs Kafka:
  - RabbitMQ: task (bajarilgach o'chadi); routing murakkab
  - Kafka: event log (saqlanadi, replay); throughput, event sourcing 9.7-bob

  → Kafka: event sourcing 9.7-bob, analytics, audit, juda katta oqim

Kafka (event streaming — RabbitMQ'dan farqli): event log (o'chmaydi — saqlanadi, replay — qayta o'qish), topic+partition (parallel, tartib partition ichida), ko'p consumer guruh (har biri butun stream). Juda yuqori throughput (millionlab/sek). RabbitMQ vs Kafka: RabbitMQ — task (bajarilgach o'chadi, routing); Kafka — event log (saqlanadi, replay, throughput). Qachon Kafka: event sourcing 9.7-bob, analytics, audit 8.26-bob, juda katta oqim. Kafka og'irroq (operatsion). Tanlov ehtiyojga.

Kafka modeli: log, partition, offset, consumer group. RabbitMQ navbatda xabar o'qilgach o'chadi. Kafka esa append-only log — xabar o'qilgandan keyin ham qoladi (retention muddatigacha). Consumer qayerda ekanini o'zi belgilaydi (offset):

text
  TOPIC "order.events" — 3 partition'ga bo'lingan (parallel):

  Partition 0: [e0][e1][e2][e3][e4]...       ← har xabar offset (0,1,2,...)
  Partition 1: [e0][e1][e2]...                  tartib faqat partition ICHIDA
  Partition 2: [e0][e1][e2][e3]...

  - Partition kaliti (key) → qaysi partition (bir key → doim bir partition
    → o'sha kalitning tartibi kafolatlanadi, masalan bir order ID uchun)
  - Offset: consumer nechanchi xabargacha o'qigani (kursor)
  - Consumer group: bir guruhdagi consumerlar partitionlarni BO'LIB oladi
    (parallel), har partitionni guruh ichida FAQAT bittasi o'qiydi

Consumer group — bir stream, ko'p mustaqil o'quvchi. Kafka'ning eng muhim farqi: bir topic'ni bir nechta guruh mustaqil o'qiydi, har biri o'z offset'i bilan:

text
  Topic "order.events"
     │
     ├─→ Group "analytics"    (o'z offset'i — hisobot uchun)
     ├─→ Group "notification" (o'z offset'i — email uchun)
     └─→ Group "audit"        (o'z offset'i — log uchun)

  → Har guruh butun stream'ni to'liq oladi (RabbitMQ fanout'ga o'xshash, lekin
    saqlanadigan, replay qilinadigan). Guruh ichida — yuk taqsimoti (2.6d).

Retention va replay (Kafka'ning superkuchi). Xabar retention muddatigacha (masalan 7 kun, yoki cheksiz) diskda qoladi — consumer o'chirmaydi:

text
  - Retention time/size: log qancha saqlanadi (vaqt yoki hajm bo'yicha)
  - Replay: yangi consumer offset=0 dan boshlab BUTUN tarixni qayta o'qiydi
    → yangi analytics xizmati → o'tgan barcha eventlarni qayta ishlaydi
    → bug tuzatildi → eventlarni qayta "o'ynatib" holatni tiklash (9.7 Event Sourcing)
  - Log compaction: bir key uchun faqat oxirgi qiymatni saqlash (holat jurnali)

Kafka chuqur: topic → partitionlarga bo'linadi (parallel throughput); tartib faqat partition ichida kafolatlanadi (kalit → doim bir partition → o'sha kalit uchun tartib). Offset — consumer kursori (Kafka o'chirmaydi, consumer siljitadi). Consumer group — bir topicni ko'p guruh mustaqil o'qiydi (har biri o'z offset'i); guruh ichida partitionlar bo'linadi (yuk taqsimoti). Retention — log muddat/hajmgacha saqlanadi → replay (yangi consumer tarixni qayta o'qiydi, Event Sourcing — 9.7). RabbitMQ vs Kafka jamlama: boy routing + task o'chadi kerak bo'lsa → RabbitMQ; katta throughput + saqlash + replay + ko'p mustaqil consumer → Kafka. Ikkovi bir tizimda birga bo'lishi mumkin.

2.6a. Redis Pub/Sub va Streams (yengil variant)

Ko'p tizimda Redis allaqachon bor (kesh — 6-qism). Uni ham xabar almashishga ishlatish mumkin — ikki rejimda:

text
  REDIS PUB/SUB (fire-and-forget — saqlamaydi):
  PUBLISH kanal xabar → o'sha payt tinglayotgan hamma oladi
  ✗ Offline subscriber xabarni O'TKAZIB yuboradi (saqlanmaydi — at-most-once)
  ✓ Juda tez, oddiy (real-time signal, kesh invalidatsiya, live counter)
  → "hozir kim tinglasa" (yo'qolsa muhim emas) uchun

  REDIS STREAMS (log — saqlanadi, RabbitMQ+Kafka orasi):
  XADD stream * maydon qiymat → log'ga qo'shiladi (ID bilan)
  ✓ Saqlanadi, consumer group (XREADGROUP), ack, replay
  ✓ Kafka'ga o'xshash yengil variant (alohida broker o'rnatmasdan)
  → o'rta hajm, Redis allaqachon bor bo'lganda (Kafka og'ir bo'lsa)

Redis Pub/Sub va Streams: Pub/Sub — fire-and-forget (saqlamaydi, offline subscriber o'tkazib yuboradi — at-most-once); tez va oddiy (real-time signal, kesh invalidatsiya, live hisoblagich). Streams — saqlanadigan log (consumer group, ack, replay — Kafka'ning yengil variantiga o'xshash). Qachon Redis: Redis allaqachon bor va alohida broker (Kafka/RabbitMQ) og'irlik qiladigan o'rta hajmli holatlarda. Katta miqyos → Kafka; boy routing → RabbitMQ; yengil/mavjud infra → Redis Streams.

2.6b. GraphQL va federation (qisqacha — 17-bob)

REST'ning over/under-fetching muammosini (2.2) GraphQL hal qiladi: mijoz aynan kerakli maydonlarni bitta so'rovda so'raydi. Mikroservislarda esa GraphQL federation — bir necha xizmatning grafini bitta yagona sxemaga birlashtiradi:

text
  GraphQL (bir so'rov, aniq shakl):
  query { user(id:42) { ism  orders { summa } } }
  → faqat ism + orders.summa keladi (over/under-fetch yo'q)

  FEDERATION (mikroservislarda):
  Gateway ← User subgraph (user maydonlari)
         ← Order subgraph (order maydonlari, @key bilan user'ga ulanadi)
  → mijoz uchun bitta grafik, ichkarida ko'p xizmat (9.8 API Gateway)

GraphQL/federation (17-bob): GraphQL — mijoz kerakli maydonlarni bitta so'rovda so'raydi (over/under-fetching yo'q — 2.2). Federation — bir necha mikroservis sxemasini bitta grafga birlashtiradi (Gateway — 9.8); har xizmat o'z subgrafini beradi, @key orqali entity'lar ulanadi. Bu — tashqi/mijoz qatlamining alternativasi (REST o'rniga yoki yonida); ichkarida hamon gRPC/queue bo'lishi mumkin. To'liq — 17-bob.

2.6c. Delivery kafolati (at-most / at-least / exactly-once)

Tarmoq ishonchsiz 2.9-bob → xabar necha marta yetkaziladi? Uch kafolat darajasi bor va bu tanlov tizim to'g'riligini belgilaydi:

text
  AT-MOST-ONCE (ko'pi bilan bir marta):
  Yubor → ack kutma → o'chir. Xato bo'lsa xabar YO'QOLADI.
  → tez, oddiy; yo'qolsa muhim emas (metrika, log — Redis Pub/Sub)

  AT-LEAST-ONCE (kamida bir marta — eng keng):
  Yubor → ack kelmasa QAYTA yubor. Ba'zan IKKI marta yetadi (dublikat).
  → yo'qotmaslik muhim; lekin consumer IDEMPOTENT bo'lishi shart 2.9-bob

  EXACTLY-ONCE (aniq bir marta — qiyin/qimmat):
  Broker + consumer transaksiya/dedup bilan aniq bir marta ta'minlaydi.
  → Kafka transaksiya, yoki at-least-once + idempotency (amalda ko'p shu)

Delivery kafolati: at-most-once (ko'pi bilan bir — yo'qolishi mumkin; tez, metrika/log); at-least-once (kamida bir — dublikat bo'lishi mumkin; eng keng ishlatiladi); exactly-once (aniq bir — qiyin/qimmat; transaksiya yoki broker qo'llovi kerak). Amalda ko'pchilik at-least-once + idempotency (2.9, 8.20: 2.5) tanlaydi — sof exactly-once qimmat va kamdan-kam kerak. Muhim: at-least-once → consumer idempotent bo'lishi SHART (dublikat zarar keltirmasin — Misol 8).

2.6d. Message pattern'lar (aloqa naqshlari)

Transportdan (REST/gRPC/queue) yuqorida — mavhum aloqa naqshlari turadi. Bir necha asosiy naqsh butun sohani qamraydi:

text
  REQUEST/REPLY (so'rov-javob):
  A → so'rov → B → javob → A   (sinxron REST/gRPC; yoki queue'da reply-to + correlationId)

  PUBLISH/SUBSCRIBE (e'lon/obuna):
  Producer → event → hamma qiziqqan subscriber (bir-birini bilmaydi)
  → fanout (RabbitMQ), consumer group (Kafka), Redis Pub/Sub — bo'shashgan

  COMPETING CONSUMERS (raqobatlashuvchi consumerlar):
  Bir navbat → ko'p bir xil consumer → har xabarni FAQAT BITTASI oladi
  → yuk taqsimoti, gorizontal masshtab (ko'p worker — 8.22)

  FAN-OUT / FAN-IN:
  Fan-out: bir so'rov → ko'p parallel ish (bo'lib berish)
  Fan-in:  ko'p natija → bir joyga yig'ish (aggregation)

Message pattern'lar: request/reply (so'rov-javob — sinxron, yoki queue'da reply-to + correlationId); publish/subscribe (bir event → ko'p mustaqil subscriber — bo'shashgan, event-driven 9.7); competing consumers (bir navbat, ko'p bir xil worker, har xabarni bittasi oladi — yuk taqsimoti, masshtab); fan-out/fan-in (ishni bo'lib berish / natijalarni yig'ish). Bu naqshlar transportdan mustaqil — RabbitMQ, Kafka, hatto REST bilan ham qurish mumkin. To'g'ri naqshni tanlash aloqa dizaynining o'zagi (9.7 event-driven bilan chambarchas).

2.6e. Message ordering va backpressure

Ikki nozik, lekin production'da og'riqli mavzu — tartib va yuk bosimi:

text
  ORDERING (tartib):
  - Kafka: tartib faqat PARTITION ichida (bir key → bir partition → tartibli)
    → tartib kerak bo'lgan xabarlarga bir xil key (masalan orderId)
  - RabbitMQ: bir navbat + bir consumer → tartibli; ko'p consumer → tartib buziladi
  ❗ Parallellik ↔ tartib — ziddiyat (parallel tez, lekin tartib yo'qoladi)

  BACKPRESSURE (yuk bosimi):
  Producer consumer'dan TEZ ishlab chiqarsa → navbat cheksiz o'sadi (xotira/disk to'ladi)
  Himoya:
  - Bounded queue (chegara) + rad etish/sekinlashtirish
  - Prefetch cheklovi 2.5-bob, consumer masshtabi (ko'proq worker)
  - gRPC/HTTP2: oqim nazorati (flow control) o'rnatilgan (avtomatik)

Ordering: tartib parallellik bilan ziddiyatda. Kafka — tartib faqat partition ichida (tartibli bo'lishi kerak xabarlarga bir xil kalit — masalan orderId); RabbitMQ — bir consumer tartibli, ko'p consumer tartibni buzadi. Backpressure — producer consumerdan tez ishlab chiqarsa navbat cheksiz o'sadi (xotira to'ladi); himoya: bounded queue (chegara), prefetch 2.5-bob, ko'proq worker, yoki gRPC/HTTP/2'ning o'rnatilgan oqim nazorati. Tartib va backpressure — sync'da (gRPC flow control) va async'da (partition kalit, prefetch) har xil hal qilinadi.

2.7. Uchta usul taqqoslash (jadval)

text
  ┌─────────────┬──────────┬───────────┬──────────────────┐
  │             │ REST     │ gRPC      │ Message Queue    │
  ├─────────────┼──────────┼───────────┼──────────────────┤
  │ Turi        │ sinxron  │ sinxron   │ asinxron         │
  │ Format      │ JSON     │ Protobuf  │ har xil          │
  │ Tezlik      │ o'rtacha │ tez (5x)  │ (fon)            │
  │ Shartnoma   │ yo'q     │ .proto    │ event schema     │
  │ Bog'liqlik  │ qattiq   │ qattiq    │ bo'shashgan      │
  │ Streaming   │ cheklangan│ bor      │ (stream — Kafka) │
  │ Brauzer     │ ✓        │ gRPC-Web  │ ✗                │
  │ Qachon      │ public   │ ichki tez │ fon/event        │
  └─────────────┴──────────┴───────────┴──────────────────┘

Taqqoslash: REST (sinxron, JSON, universal, public API); gRPC (sinxron, Protobuf, tez/tipli, ichki xizmatlar); Message Queue (asinxron, bo'shashgan, fon/event). Ular raqobatchi emas — har biri o'z o'rni: tashqi mijoz → REST; ichki tez aloqa → gRPC; fon ish/event → queue. Real tizim uchalasini ham ishlatadi (hybrid — 2.10). Tanlov — sinxron/asinxron + ichki/tashqi + tezlik.

2.8. Circuit Breaker (sinxron himoya)

text
  MUAMMO (sinxron): B xizmat yiqilsa/sekinlasa → A ham bloklanadi
  → kaskad nosozlik (A → B → C, B yiqilsa hammasi)

  CIRCUIT BREAKER (avtomat o'chirgich kabi):
  - CLOSED: normal (so'rovlar o'tadi)
  - OPEN: B ko'p xato berdi → so'rov YUBORILMAYDI (darrov xato/fallback)
  - HALF-OPEN: biroz keyin sinab ko'rish (tuzaldimi?)

  → B yiqilsa, A uni "bombardimon" qilmaydi (B tiklanishiga imkon)
  → A fallback beradi (kesh, default) — to'liq yiqilmaydi

Circuit Breaker (sinxron himoya — muhim): sinxron'da B yiqilsa A bloklanadi → kaskad nosozlik (A→B→C). Circuit breaker (avtomat o'chirgich): CLOSED (normal), OPEN (B ko'p xato → so'rov yuborilmaydi, darrov fallback), HALF-OPEN (keyin sinash). B yiqilsa A uni bombardimon qilmaydi (tiklanishiga imkon) + fallback (kesh/default — to'liq yiqilmaydi). Sinxron mikroservisda majburiy (resilience). Kutubxonalar: opossum (Node.js). Asinxron'da bu muammo yo'q (queue buferlaydi).

2.9. Ishonchlilik (retry, timeout, idempotency)

text
  TARMOQ ISHONCHSIZ → himoya kerak:
  ✓ TIMEOUT: javob kutish chegarasi (cheksiz kutma — 5s)
  ✓ RETRY: vaqtinchalik xato → qayta urinish (backoff+jitter — 8.20: 2.8)
  ✓ IDEMPOTENCY: retry ikki marta bajarmasligi (8.20: 2.5)
  ✓ CIRCUIT BREAKER: kaskad himoya 2.8-bob
  ✓ FALLBACK: xato bo'lsa — default/kesh (to'liq yiqilmaslik)

  ❗ "Tarmoq ishonchli" — noto'g'ri taxmin (fallacies of distributed computing)
  → har tarmoq chaqiruvi xato bo'lishi mumkin (himoyalanish kerak)

Ishonchlilik (tarmoq ishonchsiz — "fallacies of distributed computing"): timeout (cheksiz kutma — 5s), retry (vaqtinchalik xato → qayta — backoff+jitter — 8.20: 2.8), idempotency (retry ikki marta bajarmasin — 8.20: 2.5), circuit breaker 2.8-bob, fallback (default/kesh). Monolitda (funksiya chaqiruvi) bu muammolar yo'q — mikroservis qo'shadi (9.5: 2.2). Har tarmoq chaqiruvi xato bo'lishi mumkin (himoyalanish majburiy). Bu — taqsimlangan tizim murakkabligi.

2.9a. Bulkhead va correlation ID

Resilience'ning yana ikki muhim vositasi — bulkhead (izolyatsiya) va correlation ID (kuzatuv):

text
  BULKHEAD (kema bo'lmalari kabi — izolyatsiya):
  Bir xizmatga so'rovlar uchun ALOHIDA resurs havzasi (thread/ulanish limiti)
  → bir sekin qaram (masalan Payment) butun A'ning barcha threadlarini
    "band qilib" qo'ymaydi (boshqa yo'nalishlar ishlaydi)
  → kemadagi suv o'tkazmas bo'lmalar: bir teshik butun kemani cho'ktirmaydi

  CORRELATION ID (so'rovni uchidan-uchiga kuzatish):
  Kiruvchi so'rovga bitta ID → hamma xizmat/queue xabariga uzatiladi (header)
  → bir foydalanuvchi harakatini A→B→queue→C bo'ylab loglardan tiklash
  → distributed tracing asosi (OpenTelemetry, Jaeger — 10-qism)

Bulkhead — resurslarni izolyatsiya (har qaram xizmatga alohida thread/ulanish havzasi); bir sekin qaram butun tizimning resurslarini band qilmaydi (kemadagi suv o'tkazmas bo'lmalar). Correlation ID — kiruvchi so'rovga bitta ID beriladi va barcha xizmat/queue xabarlariga uzatiladi (header) → bir harakatni A→B→queue→C bo'ylab loglardan tiklash mumkin (distributed tracing asosi — 10-qism). Bulkhead + circuit breaker + timeout + retry — resilience'ning to'liq to'plami (Polly — .NET, opossum — Node.js).

2.9b. Service mesh (sidecar, Istio — qisqacha)

Yuqoridagi barcha resilience mantig'ini (retry, timeout, circuit breaker, mTLS, tracing) har xizmat kodiga yozish o'rniga, uni infratuzilma qatlamiga ko'chirish mumkin — bu service mesh:

text
  SERVICE MESH — sidecar proxy naqshi:
  Har xizmat yonida (podda) SIDECAR proxy (Envoy) ishlaydi
  Xizmat A → [A-sidecar] ──tarmoq──→ [B-sidecar] → Xizmat B

  Sidecar hal qiladi (xizmat kodi TEGMAYDI):
  - Retry, timeout, circuit breaker (traffic policy)
  - mTLS (shifrlangan xizmatlararo aloqa)
  - Load balancing, kuzatuv (metrika, trace)
  → Istio, Linkerd (control plane sidecarlarni boshqaradi)

Service mesh (Istio/Linkerd): resilience va tarmoq mantig'ini xizmat kodidan sidecar proxyga (Envoy — har pod yonida) ko'chiradi. Retry/timeout/circuit breaker/mTLS/load balancing/tracing — deklarativ siyosat sifatida, xizmat kodiga tegmasdan. Qachon: ko'p xizmatli yetuk tizim (har tilda bir xil resilience kerak). Narx: operatsion murakkablik (har pod'da qo'shimcha proxy). Kichik tizimda ortiqcha — kutubxona (opossum/Polly) yetarli. Chuqurroq — 10-qism (DevOps/Kubernetes).

2.9c. Schema evolution (proto/Avro versiyalash)

Xizmatlar mustaqil deploy bo'ladi 9.5-bob → producer va consumer turli versiyada bo'lishi mumkin. Shuning uchun xabar/shartnoma orqaga va oldinga mos (backward/forward compatible) evolyutsiya qilishi shart:

text
  PROTOBUF (gRPC — 2.4):
  ✓ Yangi maydon QO'SHISH — yangi raqam bilan (eski kod e'tiborsiz qoldiradi)
  ✓ Maydonni "olib tashlash" — raqamni QAYTA ISHLATMASLIK (reserved)
  ✗ Mavjud maydon RAQAMINI yoki turini o'zgartirish — BUZADI
  → raqam = binary shartnoma; qo'shish xavfsiz, o'zgartirish xavfli

  AVRO (Kafka — ko'p ishlatiladi):
  Schema Registry — sxemalar markazda saqlanadi va moslik tekshiriladi
  → producer sxema o'zgarsa, registry backward/forward mosligini validatsiya qiladi
  → eski consumer yangi eventni, yangi consumer eski eventni o'qiy oladi

Schema evolution: xizmatlar mustaqil deploy → shartnoma orqaga/oldinga mos bo'lishi shart. Protobuf (gRPC): yangi maydon qo'shish xavfsiz (raqam bilan), maydon raqamini/turini o'zgartirish yoki qayta ishlatish BUZADI (reserved bilan himoyalang). Avro (Kafka): Schema Registry sxemalarni markazda saqlaydi va moslikni validatsiya qiladi (eski/yangi consumer bir-birining eventini o'qiy oladi). Bu — mustaqil deploy va Event Sourcing'ning 9.7-bob shartsiz talabi: xabar formatini "buzmasdan" rivojlantirish. Qoida: qo'sh — o'chirma/o'zgartirma.

2.9d. Sinxron yoki asinxron — tanlov jadvali

Butun bobning amaliy jamlamasi — qaysi holatda qaysi usul:

text
  ┌──────────────────────────────────┬───────────────────────────────┐
  │ Vaziyat                          │ Tanlov                         │
  ├──────────────────────────────────┼───────────────────────────────┤
  │ Javob DARROV kerak (mijoz kutadi)│ Sinxron (REST/gRPC)            │
  │ Fon ish (email, video, hisobot)  │ Asinxron (RabbitMQ task)       │
  │ Bir voqea → ko'p mustaqil xizmat │ Asinxron pub/sub (Kafka)       │
  │ Tashqi mijoz / public API        │ REST (yoki GraphQL)            │
  │ Ichki xizmatlararo, tez/ko'p     │ gRPC (binary, tipli)           │
  │ Real-time oqim (narx, chat, IoT) │ gRPC streaming / WebSocket     │
  │ Katta oqim + saqlash + replay    │ Kafka                          │
  │ Boy routing + task o'chishi      │ RabbitMQ                       │
  │ Yengil, Redis bor, o'rta hajm    │ Redis Streams/Pub-Sub          │
  │ Kuchli izchillik (bitta so'rovda)│ Sinxron (transaksiya nazorati) │
  │ Yuqori mustaqillik/chidamlilik   │ Asinxron (bog'liqlik kam)      │
  └──────────────────────────────────┴───────────────────────────────┘

  ❗ Umumiy tamoyil: iloji bo'lsa asinxron (bog'liqlik kam, chidamli — 9.5);
     lekin darrov javob va izchillik kerak bo'lganda — sinxron.

Tanlov jadvali (amaliy jamlama): darrov javob → sinxron (REST/gRPC); fon ish → RabbitMQ task; bir voqea → ko'p xizmat → Kafka pub/sub; tashqi → REST/GraphQL; ichki tez → gRPC; real-time oqim → gRPC streaming; katta oqim+replay → Kafka; boy routing → RabbitMQ; yengil/mavjud infra → Redis Streams. Bosh qoida: iloji bo'lsa asinxron (chidamlilik, mustaqillik — 9.5); darrov javob/izchillik kerakda — sinxron.

2.10. Hybrid (qaysi joyda qaysi)

text
  REAL TIZIM — uchalasini ishlatadi (har joyda mos usul):

  Mijoz (brauzer/mobil) → REST/GraphQL (Gateway — 9.8)
                              │
                    ┌─────────┼─────────┐
                    ▼ gRPC    ▼ gRPC     ▼ gRPC      ← ichki (tez, tipli)
                 User      Order      Product
                 Service   Service    Service
                    │
                    └─→ event (Kafka/RabbitMQ) → Notification, Analytics, Audit
                                                  (asinxron — fon, event)

  → Tashqi: REST; ichki sinxron: gRPC; fon/event: queue
  → "Start REST → gRPC tez joyga → queue async kerak bo'lganda"

Hybrid (real tizim — uchalasini): tashqi mijoz → REST/GraphQL (Gateway — 9.8); ichki sinxron → gRPC (tez, tipli); fon/event → message queue (asinxron). Har joyda mos usul (bittasi hammaga emas). Evolyutsiya: "start REST (oddiy) → gRPC tez ichki joyga → queue async kerak bo'lganda". Modular monolit'da 9.5-bob — funksiya chaqiruvi (eng oddiy); mikroservisda — bu usullar. To'g'ri kombinatsiya — samarali, chidamli tizim.

2.11. NestJS'da (8.16 takrori — qisqa)

typescript
// NestJS — transport-agnostik (bir kod, ko'p transport — 8.16: 2.4)
// gRPC
const app = await NestFactory.createMicroservice(AppModule, {
  transport: Transport.GRPC,
  options: { package: "user", protoPath: "user.proto" },
});
// RabbitMQ
{ transport: Transport.RMQ, options: { urls: ["amqp://..."], queue: "tasks" } }
// Kafka
{ transport: Transport.KAFKA, options: { client: { brokers: ["localhost:9092"] } } }

NestJS'da (8.16: 2.4 takrori): transport-agnostik — bir xil handler kodi (@MessagePattern/@EventPattern), faqat transport o'zgaradi (GRPC/RMQ/KAFKA). gRPC — .proto 2.4-bob; RabbitMQ — queue; Kafka — brokers. NestJS abstraksiya (transport almashtirsa kod tegmaydi). Bu — NestJS kuchi 8.16-bob. Tafsilot — 8.16'da; bu yerda arxitektura nuqtai nazaridan.

2.12. Best practices (aloqa)

text
  ✓ Sinxron (REST/gRPC) — javob darrov kerak; asinxron (queue) — fon/event 2.1-bob
  ✓ Tashqi → REST; ichki tez → gRPC; fon → queue 2.10-bob
  ✓ Iloji bo'lsa asinxron (bog'liqlik kam — chidamli — 9.5: 2.11)
  ✓ Sinxron'da: circuit breaker + timeout + retry + fallback (2.8, 2.9)
  ✓ Idempotency (retry himoyasi — 8.20: 2.5)
  ✓ gRPC ichki (tez, tipli — .proto shartnoma — 2.3, 2.4)
  ✓ RabbitMQ (task) vs Kafka (event log/replay — 2.5, 2.6)
  ✓ Sinxron zanjirdan saqlanish (A→B→C→D — latency/bog'liqlik — 2.1)
  ✓ Modular monolit → funksiya chaqiruvi (eng oddiy — 9.5)

3. Sintaksis — tez ma'lumotnoma

text
SINXRON: REST (HTTP+JSON, universal/public) | gRPC (Protobuf, ichki tez)
ASINXRON: RabbitMQ (task) | Kafka (event log, replay)

gRPC 2.4-bob: .proto → service + message → kod generatsiya
Queue 2.5-bob: producer → [QUEUE] → consumer (ack/nack)
Himoya (2.8, 2.9): timeout + retry + circuit breaker + fallback + idempotency

NestJS 2.11-bob: Transport.GRPC | Transport.RMQ | Transport.KAFKA

4. Batafsil kod namunalari

Misol 1 — REST aloqa (sinxron — 2.2)

typescript
// Xizmat A → Xizmat B (REST — sinxron, javob kutadi)
@Injectable()
export class OrderService {
  constructor(private http: HttpService) {}           // (2.18-JS Axios)

  async buyurtmaYarat(dto: CreateOrderDto) {
    // User xizmatidan ma'lumot (sinxron — REST)
    const { data: user } = await firstValueFrom(
      this.http.get(`http://user-service:3001/users/${dto.userId}`, {
        timeout: 5000,                                // TIMEOUT (2.9 — cheksiz kutma)
      }).pipe(
        retry({ count: 2, delay: 1000 }),             // RETRY (2.9)
        catchError(() => { throw new ServiceUnavailableException("User xizmat javob bermadi"); }),
      ),
    );
    // ...
  }
}
// ❗ REST oddiy, lekin sinxron (user-service yiqilsa → bu ham xato)

Misol 2 — gRPC server (NestJS — 2.3, 2.11)

typescript
// user.proto (2.4)
// service UserService { rpc GetUser (GetUserRequest) returns (User); }

// User mikroservis (gRPC server)
@Controller()
export class UserGrpcController {
  constructor(private usersService: UsersService) {}

  @GrpcMethod("UserService", "GetUser")              // .proto metod
  async getUser(data: { id: string }): Promise<any> {
    const user = await this.usersService.bitta(data.id);
    return { id: user.id, ism: user.ism, email: user.email };   // .proto User
  }
}

// main.ts — gRPC transport
const app = await NestFactory.createMicroservice(AppModule, {
  transport: Transport.GRPC,
  options: { package: "user", protoPath: join(__dirname, "user.proto") },
});

Misol 3 — gRPC klient (boshqa xizmat — 2.3)

typescript
// Order xizmat → User xizmat (gRPC — tez, tipli)
@Injectable()
export class OrderService implements OnModuleInit {
  private userService: any;
  constructor(@Inject("USER_PACKAGE") private client: ClientGrpc) {}

  onModuleInit() {
    this.userService = this.client.getService("UserService");   // .proto'dan
  }

  async buyurtma(userId: string) {
    // gRPC chaqiruv (binary, HTTP/2 — REST'dan tez)
    const user = await firstValueFrom(this.userService.getUser({ id: userId }));
    return user;                                       // tipli (.proto shartnoma)
  }
}
// Module: ClientsModule.register([{ name: "USER_PACKAGE", transport: Transport.GRPC, options: {...} }])

Misol 4 — gRPC streaming (real-time — 2.3)

typescript
// Server stream — ko'p javob (real-time — masalan, jonli narx)
@GrpcStreamMethod("PriceService", "WatchPrice")
watchPrice(data$: Observable<any>): Observable<any> {
  return new Observable((observer) => {
    const interval = setInterval(() => {
      observer.next({ narx: this.getCurrentPrice() });   // har sekund yangi narx (stream)
    }, 1000);
    return () => clearInterval(interval);
  });
}
// ❗ gRPC streaming — REST qila olmaydigan (bi-directional real-time)
// → jonli narx, chat, IoT telemetriya (tez, samarali)

Misol 5 — RabbitMQ (task queue — 2.5)

typescript
// Producer — vazifa navbatga (asinxron — kutmaydi)
@Injectable()
export class OrderService {
  constructor(@Inject("TASK_QUEUE") private client: ClientProxy) {}

  async buyurtmaYarat(dto: any) {
    const order = await this.repo.save(dto);
    // Email yuborish — navbatga (fon — kutmaydi, 8.22)
    this.client.emit("send_invoice_email", { orderId: order.id });   // asinxron
    return order;                                     // darrov javob (email fonda)
  }
}

// Consumer — boshqa xizmat (keyin oladi, ack)
@EventPattern("send_invoice_email")
async sendInvoice(@Payload() data: any, @Ctx() ctx: RmqContext) {
  const channel = ctx.getChannelRef();
  const msg = ctx.getMessage();
  try {
    await this.mailService.invoiceYubor(data.orderId);
    channel.ack(msg);                                 // muvaffaqiyat → tasdiq (2.5)
  } catch {
    channel.nack(msg, false, false);                 // xato → DLQ (8.20: 2.9)
  }
}

Misol 5a — RabbitMQ topic exchange va prefetch (2.5)

typescript
// Topic exchange + binding + prefetch (adolatli taqsimot) — amqplib bilan
import * as amqp from "amqplib";

async function setup() {
  const conn = await amqp.connect("amqp://localhost");
  const ch = await conn.createChannel();

  // 1) Exchange (topic — pattern bo'yicha yo'naltirish, 2.5)
  await ch.assertExchange("orders", "topic", { durable: true });

  // 2) Queue + DLQ bog'lash (zaharli xabar → dead-letter, 2.5)
  await ch.assertQueue("orders.eu", {
    durable: true,                                  // disk (broker qayta ishga tushsa saqlanadi)
    deadLetterExchange: "orders.dlx",               // xato → DLQ
  });

  // 3) Binding — routing key pattern (* = 1 so'z, # = ko'p)
  await ch.bindQueue("orders.eu", "orders", "order.*.eu");   // "order.created.eu" mos

  // 4) Prefetch — bir vaqtda 1 xabar (og'ir vazifa → adolat, 2.5)
  await ch.prefetch(1);

  ch.consume("orders.eu", async (msg) => {
    if (!msg) return;
    try {
      await ishla(JSON.parse(msg.content.toString()));
      ch.ack(msg);                                  // muvaffaqiyat → tasdiq
    } catch {
      ch.nack(msg, false, false);                   // xato → DLQ (requeue emas)
    }
  });
}
// ❗ Producer: ch.publish("orders", "order.created.eu", Buffer.from(JSON.stringify(data)))

Misol 5b — Correlation ID (uchidan-uchiga kuzatuv — 2.9a)

typescript
// Kiruvchi so'rovga ID → hamma downstream chaqiruvga uzatiladi (tracing)
@Injectable()
export class CorrelationMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    // Bor bo'lsa qabul qil, bo'lmasa yarat (chegara xizmat)
    req.correlationId = req.headers["x-correlation-id"] ?? randomUUID();
    res.setHeader("x-correlation-id", req.correlationId);
    next();
  }
}

// Downstream chaqiruvda uzatish (REST/gRPC/queue — barchasida header sifatida)
async buyurtma(userId: string, correlationId: string) {
  await firstValueFrom(
    this.http.get(`http://user-service/users/${userId}`, {
      headers: { "x-correlation-id": correlationId },   // zanjir bo'ylab uzatiladi
    }),
  );
  // queue'ga ham: this.client.emit("evt", { data, correlationId })
}
// ❗ Barcha loglarda shu ID → bir foydalanuvchi harakatini A→B→queue→C tiklash

Misol 6 — Kafka (event stream — 2.6)

typescript
// Kafka — event log (saqlanadi, replay, ko'p consumer)
// Producer — event chiqaradi
@Injectable()
export class OrderService {
  constructor(@Inject("KAFKA") private kafka: ClientKafka) {}

  async buyurtmaYarat(dto: any) {
    const order = await this.repo.save(dto);
    // Event (Kafka topic'ga — ko'p consumer o'qiydi: analytics, notification, audit)
    this.kafka.emit("order.events", {
      key: order.id,                                  // partition kaliti (tartib)
      value: { type: "OrderCreated", orderId: order.id, summa: order.summa },
    });
    return order;
  }
}
// Har consumer guruhi butun stream'ni o'qiydi (analytics, audit — 8.26 mustaqil)
// ❗ Event saqlanadi — yangi consumer keyin qo'shilsa, tarixni replay qiladi

Misol 7 — Circuit Breaker (2.8)

typescript
import * as CircuitBreaker from "opossum";

@Injectable()
export class PaymentClient {
  private breaker: CircuitBreaker;

  constructor(private http: HttpService) {
    this.breaker = new CircuitBreaker(
      (data: any) => firstValueFrom(this.http.post("http://payment:3002/charge", data)),
      {
        timeout: 3000,                                // 3s javob (2.9)
        errorThresholdPercentage: 50,                 // 50% xato → OPEN
        resetTimeout: 30000,                          // 30s keyin HALF-OPEN (sinash)
      },
    );
    // Fallback — circuit OPEN bo'lsa (B yiqilgan)
    this.breaker.fallback(() => ({ status: "pending", message: "To'lov keyinroq qayta urinilad" }));
  }

  async tolov(data: any) {
    return this.breaker.fire(data);                   // breaker orqali (himoyalangan)
  }
}
// ❗ Payment yiqilsa → breaker OPEN → fallback (to'liq yiqilmaydi — 2.8)

Misol 8 — Idempotency (retry himoyasi — 2.9)

typescript
// Sinxron retry / queue redelivery → ikki marta bajarmaslik (8.20: 2.5)
@EventPattern("process_payment")
async processPayment(@Payload() data: { paymentId: string; orderId: string }) {
  // Idempotency — bu payment allaqachon ishlangmi?
  const mavjud = await this.repo.findOneBy({ paymentId: data.paymentId });
  if (mavjud) return;                                 // takror → o'tkazib yubor (8.20: 2.5)

  await this.repo.save({ paymentId: data.paymentId, orderId: data.orderId, status: "done" });
  // ... haqiqiy ishlov
}
// ❗ Retry/redelivery bo'lsa ham — bir marta bajariladi (idempotent)

Misol 9 — Aloqa tanlovi (qaror — 2.7, 2.10)

text
  Loyihada qaysi usul? (qaror):

  Mijoz buyurtma ko'radi (darrov ma'lumot kerak)
  → REST/gRPC (sinxron — javob kerak)

  Buyurtma yaratilganda email yuborish (fon — kutib bo'lmaydi)
  → Message queue (asinxron — RabbitMQ task)

  Buyurtma → analytics + audit + notification (ko'p tinglovchi)
  → Kafka (event stream — har biri mustaqil o'qiydi)

  Ichki: Order → User ma'lumoti (tez, ko'p so'rov)
  → gRPC (tez, tipli)

  Tashqi: mobil ilova → backend
  → REST (universal)

Misol 10 — To'liq hybrid arxitektura (2.10)

text
  Real e-commerce aloqa arxitekturasi:

  Mobil/Web ──REST──→ API Gateway 9.8-bob
                          │
              ┌───────────┼───────────┐
              │ gRPC      │ gRPC       │ gRPC     ← ichki sinxron (tez, tipli)
              ▼           ▼            ▼
          User Svc    Order Svc    Product Svc
                          │
                          │ emit event
                          ▼
                    ┌─────────────┐
                    │ Kafka/RabbitMQ│            ← asinxron (fon, event)
                    └──────┬──────┘
              ┌────────────┼────────────┐
              ▼            ▼             ▼
         Notification  Analytics      Audit 8.26-bob
         (email/push)  (Kafka)        (event log)

  → Tashqi REST + ichki gRPC + fon/event queue (har joyda mos — 2.12)

5. To'g'ri va noto'g'ri holatlar

1) Hamma joyda REST (fon ish ham)

text
❌ email/video REST (sinxron — bloklaydi — 2.1)
✅ fon ish → message queue (asinxron)

2) Sinxron zanjir (A→B→C→D)

text
❌ uzun sinxron zanjir (latency, bog'liqlik — 2.1)
✅ asinxron / gRPC + circuit breaker

3) Tashqi mijozga gRPC

text
❌ brauzerga gRPC (qo'llamaydi — 2.3)
✅ tashqi REST; ichki gRPC

4) Circuit breaker'siz sinxron

text
❌ B yiqilsa → kaskad 2.8-bob
✅ circuit breaker + fallback

5) Idempotency'siz retry

text
❌ retry → ikki marta bajarish 2.9-bob
✅ idempotency

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Kaskad nosozlik (bir xizmat hammasini yiqitdi)

Sababi: sinxron, circuit breaker yo'q 2.8-bob. Yechimi: circuit breaker + fallback + timeout.

Xato 2 — gRPC brauzerda ishlamaydi

Sababi: brauzer gRPC qo'llamaydi 2.3-bob. Yechimi: gRPC-Web yoki tashqi REST.

Xato 3 — Xabar ikki marta ishlandi

Sababi: redelivery, idempotency yo'q 2.9-bob. Yechimi: idempotency.

Xato 4 — Sekin (sinxron zanjir)

Sababi: A→B→C→D ketma-ket 2.1-bob. Yechimi: asinxron; parallel (Promise.all); gRPC.

Xato 5 — Xabar yo'qoldi

Sababi: ack/persistence yo'q 2.5-bob. Yechimi: ack + durable queue + DLQ.

Xato 6 — .proto o'zgarishi buzdi

Sababi: maydon raqami o'zgardi 2.4-bob. Yechimi: maydon raqami o'zgartirmaslik (faqat qo'shish).


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Mikroservis (8.16, 9.5): transport.
  • Event-driven 9.7-bob: queue/Kafka.
  • API Gateway 9.8-bob: REST tashqi.
  • Navbat 8.22-bob: RabbitMQ task.
  • REST 5.7-bob: sinxron.
  • Ishonchlilik 8.20-bob: retry, idempotency.
  • Audit 8.26-bob: Kafka event log.
  • DevOps (10): xizmat deploy.

8. Eng yaxshi amaliyotlar (best practices)

  • Sinxron (REST/gRPC) — javob kerak; asinxron (queue) — fon/event 2.1-bob.
  • Tashqi → REST; ichki tez → gRPC; fon → queue 2.10-bob.
  • Iloji bo'lsa asinxron (bog'liqlik kam — 9.5: 2.11).
  • Sinxron'da: circuit breaker + timeout + retry + fallback (2.8, 2.9).
  • Idempotency (retry himoyasi — 8.20).
  • gRPC ichki (tez, tipli — .proto — 2.3, 2.4).
  • RabbitMQ (task) vs Kafka (event log/replay) (2.5, 2.6).
  • Sinxron zanjirdan saqlanish (latency/bog'liqlik — 2.1).
  • Modular monolit → funksiya chaqiruvi (eng oddiy — 9.5).
  • .proto versiyalash (maydon raqami — 2.4).

9. Amaliy loyiha: "Mikroservis Aloqa Tizimi"

Xizmatlararo aloqani amalda mustahkamlash.

Maqsad

Mikroservislarda uch usulni to'g'ri ishlatish: REST (tashqi), gRPC (ichki), queue (fon/event).

Talablar (requirements)

  1. REST: tashqi mijoz + timeout/retry (Misol 1, 2.2).
  2. gRPC server/klient: ichki xizmat (.proto — Misol 2, 3, 2.3).
  3. gRPC streaming: real-time (Misol 4).
  4. RabbitMQ: task queue (email — Misol 5, 2.5).
  5. Kafka: event stream (ko'p consumer — Misol 6, 2.6).
  6. Circuit breaker: sinxron himoya (Misol 7, 2.8).
  7. Idempotency: retry himoyasi (Misol 8, 2.9).
  8. Aloqa tanlovi: qaysi joyda qaysi (Misol 9, 2.7).
  9. Hybrid: uchalasi birga (Misol 10, 2.10).
  10. Ishonchlilik: timeout/retry/fallback 2.9-bob.

Maslahatlar (hint)

  • Sinxron/asinxron tanlovi (2.1, 1-holat).
  • gRPC ichki, REST tashqi (2.3, 3-holat).
  • Circuit breaker (2.8, 1-xato).
  • Idempotency (2.9, 3-xato).
  • RabbitMQ task vs Kafka event (2.5, 2.6).
  • Sinxron zanjirdan saqlanish (2.1, 2-holat).

"Tayyor" mezonlari (acceptance criteria)

  • REST (timeout/retry).
  • gRPC server/klient.
  • gRPC streaming.
  • RabbitMQ task.
  • Kafka event.
  • Circuit breaker.
  • Idempotency.
  • Aloqa tanlovi.
  • Hybrid.
  • Ishonchlilik.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda xizmatlararo aloqani chuqur o'rgandik:

  • Sinxron vs asinxron (asosiy farq — 2.1); REST (universal — 2.2); gRPC (tez, tipli, protobuf, streaming — 2.3, 2.4).
  • Message queue (RabbitMQ task — 2.5; Kafka event stream — 2.6); taqqoslash 2.7-bob.
  • Circuit breaker (kaskad himoya — 2.8); ishonchlilik (retry/timeout/idempotency/fallback — 2.9); hybrid 2.10-bob.

Keyingi bob — 9.7: Event-driven architecture, CQRS, Event Sourcing. Aloqa usullarini bildik; endi asinxron event'lar atrofida qurilgan arxitektura naqshlarini — event-driven, CQRS (o'qish/yozish ajratish), Event Sourcing (holat = event tarixi) — chuqur o'rganamiz. Bu — murakkab, masshtablanadigan tizimlarning ilg'or naqshlari.


Foydalanilgan rasmiy/ishonchli manbalar

gRPC va Protocol Buffers:

  • gRPC rasmiy hujjatlari — Concepts, 4 chaqiruv turi (unary/streaming), HTTP/2 asosi
  • Protocol Buffers Language Guide (proto3) — message, service, maydon raqamlari, reserved, schema evolution
  • HTTP/2 spetsifikatsiyasi (RFC 7540) — multiplexing, HPACK sarlavha siqish, flow control

Message brokerlari:

  • RabbitMQ rasmiy hujjatlari — AMQP modeli (exchange/queue/binding), exchange turlari (direct/topic/fanout/headers), prefetch (QoS), Dead-Letter Exchange
  • Apache Kafka Documentation — topic/partition/offset, consumer group, retention, log compaction, exactly-once semantikasi
  • Redis Documentation — Pub/Sub va Streams (XADD/XREADGROUP), consumer group
  • Confluent — Schema Registry va Avro moslik (backward/forward compatibility)

Naqshlar va chidamlilik (resilience):

  • Enterprise Integration Patterns (Hohpe & Woolf) — request/reply, publish/subscribe, competing consumers, message routing
  • "Release It!" (Michael Nygard) — Circuit Breaker, Bulkhead, Timeout naqshlari
  • Fallacies of Distributed Computing (Deutsch/Gosling) — tarmoq ishonchsizligi taxminlar
  • opossum (Node.js circuit breaker) va Polly (.NET) kutubxona hujjatlari

Service mesh va tracing:

  • Istio va Envoy rasmiy hujjatlari — sidecar proxy, traffic policy, mTLS
  • OpenTelemetry — distributed tracing, correlation/trace context

NestJS:

  • NestJS rasmiy hujjatlari — Microservices (transport: gRPC, RabbitMQ, Kafka), @MessagePattern/@EventPattern
Ulashish:Telegram'da

O'qiganingizni mustahkamlang

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Mikroservislar aloqasi — REST, gRPC, RabbitMQ va Kafka (9.6-bob) — IlmHamroh