WisarWisar
Dasturlash kitobi/9-QISM — Arxitektura35 daqiqa

9.6-bob: Service communication — REST, gRPC, message queues

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: exchangequeue 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 (ABC). 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 ABqueueC 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 ABqueueC 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 qoch (ABCD — 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 ABqueueC 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 (ABCD)

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)
 circuit breaker + fallback

5) Idempotency'siz retry

text
 retry  ikki marta bajarish (2.9)
 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: ABCD 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 qoch (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 qoch (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

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
9.6-bob: Service communication — REST, gRPC, message queues — Wisar