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)
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, KafkaSinxron 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)
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 mijozREST (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:
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)
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, streaminggRPC (Google RPC — ichki xizmatlar): Protobuf (binary — JSON'dan kichik/tez) + HTTP/2 (multiplexing) + strong contract (
.protofayl — 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:
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 parallelgRPC'ning 4 chaqiruv turi (streaming to'liq). .protoda stream kalit so'zi so'rov/javobga qo'yiladi va 4 kombinatsiya beradi:
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)
// 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 shartnomaProtobuf/.proto (gRPC shartnomasi):
.protofayl — 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)
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):
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'iExchange turlari (4 xil yo'naltirish). Aynan shu tanlov RabbitMQ'da xabar kimga borishini belgilaydi:
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:
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):
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)
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 oqimKafka (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):
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'qiydiConsumer 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:
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:
- 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:
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:
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,
@keyorqali 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:
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:
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:
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)
┌─────────────┬──────────┬───────────┬──────────────────┐
│ │ 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)
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 yiqilmaydiCircuit 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)
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):
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:
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:
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 oladiSchema 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 (
reservedbilan 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:
┌──────────────────────────────────┬───────────────────────────────┐
│ 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)
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)
// 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 —.proto2.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)
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
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.KAFKA4. Batafsil kod namunalari
Misol 1 — REST aloqa (sinxron — 2.2)
// 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)
// 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)
// 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)
// 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)
// 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)
// 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)
// 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 tiklashMisol 6 — Kafka (event stream — 2.6)
// 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 qiladiMisol 7 — Circuit Breaker (2.8)
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)
// 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)
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)
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)
email/video REST (sinxron — bloklaydi — 2.1)
fon ish message queue (asinxron)2) Sinxron zanjir (ABCD)
uzun sinxron zanjir (latency, bog'liqlik — 2.1)
asinxron / gRPC + circuit breaker3) Tashqi mijozga gRPC
brauzerga gRPC (qo'llamaydi — 2.3)
tashqi REST; ichki gRPC4) Circuit breaker'siz sinxron
B yiqilsa kaskad (2.8)
circuit breaker + fallback5) Idempotency'siz retry
retry ikki marta bajarish (2.9)
idempotency6. 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)
- REST: tashqi mijoz + timeout/retry (Misol 1, 2.2).
- gRPC server/klient: ichki xizmat (.proto — Misol 2, 3, 2.3).
- gRPC streaming: real-time (Misol 4).
- RabbitMQ: task queue (email — Misol 5, 2.5).
- Kafka: event stream (ko'p consumer — Misol 6, 2.6).
- Circuit breaker: sinxron himoya (Misol 7, 2.8).
- Idempotency: retry himoyasi (Misol 8, 2.9).
- Aloqa tanlovi: qaysi joyda qaysi (Misol 9, 2.7).
- Hybrid: uchalasi birga (Misol 10, 2.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!