Backend cavabının optimallaşdırılması: növbələr, async, backpressure
1) Niyə: məqsədlər və SLO
Məqsəd, hətta sıçrayışlar altında da sabit sürətli cavabdır. Biznes bu SLO ifadə edir:- API (CRUD/kataloqlar): p95 ≤ 250-400 ms, error rate <1%.
- Ödəniş/settlment (asenxron): təsdiq üçün daxili SLA ≤ 2-5 dəqiqə, müştəriyə isə ani 202/Accepted + status-poller/vebhuk.
- WS/real-time: RTT p95 ≤ 120 мс, disconnect ≤ 0. 5%.
Açar: «yavaş» addımları (provayderlər, DB, xarici API) növbələr və səlahiyyətli yük məhdudiyyəti vasitəsilə istifadəçi cavabından azad edin.
2) Əsas şəkil: latentlik harada alınır
Dar yerlər: BD (hovuzlar/indekslər), xarici provayderlər (PSP/oyun), bloklayan I/O, GC/stop-world, serializasiya JSON, «ağır» aqreqasiyalar.
Simptomları: p99 böyümə, DB-yə birləşmələrin növbəsi, retraj sıçrayışları, zaman-aut zənciri (retry storm).
Antidot: asinxron konveyerlər + backpressure + time-auts/retrailer + idempotentlik.
3) Asinxron nümunələr: SEDA və CQRS
SEDA (staged event-driven architecture): mərhələdə emal bölmək (ingress → validation → qeyd → inteqrasiya → bildiriş). Hər birinin öz növbəsi və paralellik limitləri var.
CQRS: oxu və yazıları bölün. Qeyd - jurnal/baza, oxu - proyeksiyalar/caches.
Outbox: Hadisə qeydlə birlikdə atom şəklində yayımlanır («itirilmiş» mesajlardan qaçın).
Saga: qlobal əvəzinə kompensasiya əməliyyatları ilə uzun iş prosesləri.
4) Növbələr və axınlar: seçim və sazlama
RabbitMQ/NATS JetStream - tapşırıq komandaları (work queues), Kafka - replay ilə hadisələr/axınlar.
Cavablara təsir edən parametrlər:- Prefetch/max in-flight: DB/xarici API-ni «vurmamaq» üçün eyni anda işlənmiş worker mesajlarının sayını (məsələn, 16-64) məhdudlaşdırın.
- Aker/təkrar: idempotent yazıdan sonra 'ack'; eksponensial gecikmə və jitter ilə təkrar.
- DLQ/parking lot: sonsuz retras yoxdur - N cəhd sonra Dead Letter Queue gedir.
- Partiyalaşdırma (Kafka): mahiyyətcə (userId/txnId) nizamlanması üçün açar; partiyalar sayı vasitəsilə paralellik.
5) Əks təzyiq (backpressure) - boğulmamaq üçün
Fikir: SLO-nun gecikmə həddində işləyə biləcəyiniz qədər qəbul edin.
Texnikalar:- Admission control: hər bir xarici asılılıq üçün rəqabəti (semaphore/worker-pool) məhdudlaşdırın: DB, PSP, oyun provayderi.
- Trafik Shaping: xidmət girişində və kritik marşrutlarda token-bucket/leaky-bucket.
- Yuxarı sərhədli növbələr: doldurulduqda quyruğu kəsirik (429/503 + Retry-After) və ya asap-batch-ə keçiririk.
- Adaptive concurrency (AIMD): müvəffəqiyyətlə paralelliyi artırın, zaman aşımlarında azalın.
- Circuit Breaker: 'closed → open → half-open' səhvlər/xarici API zaman-aut; open - deqradasiya (cash/stab).
go sem: = make (chan struct {}, 64 )//BD/PSP üçün rəqabət limiti
func handle(req) {
select {
case sem <- struct{}{}:
defer func(){ <-sem }()
ctx, cancel:= context. WithTimeout(req. ctx, 300time. Millisecond)
defer cancel()
res, err:= db. Do(ctx, req)
if err == context. DeadlineExceeded { metrics. Timeouts. Inc(); return TooSlow() }
return Ok(res)
default:
metrics. Backpressure. Inc()
return TooBusy(429, "Retry-After: 0. 2")
}
}
6) Time-out, retrai və jitter: «üç balina sağ»
SLO-dan daha qısadır: SLO 400 ms, DB/provayderə 250-300 ms; ümumi zaman aşımı <400-600 ms.
Retrajlar məhdud və ağıllı: 1-2 max cəhdləri, yalnız eksponent və jitter ilə təhlükəsiz əməliyyatlar üçün.
Koalessinq: Bir açar üçün təkrarları yığın.
Psevdokod (eksponent + jitter):python for attempt in range(0, 2):
try:
return call(dep, timeout=0. 3)
except Timeout:
backoff = (0. 05 (2attempt)) + random. uniform(0, 0. 05)
sleep(backoff)
raise UpstreamUnavailable
7) İdempotentlik və duplikasiya
Idempotency-Key HTTP-də (depozitlər, ödənişlər), DB-də 'operation _ id' (unikal indeks).
Inbox/Outbox: daxil olan webhucks - daima dedupe-dən 'event _ id' -ə qədər dəyişməz inbox cədvəli vasitəsilə; çıxış - əməliyyat outbox.
Exactly-once «mənasında»: təkrar çatdırılma/icra icazə, lakin bir təsiri.
8) Yavaş əməliyyatlar üçün sürətli API
Sinxron cavab: 201/202 + status URL ('/status/{ id} '), ETA və retrai ipuçları.
Webhucks/Server-Sent Events/WS - hazır olduqda push state.
Müştəri intizamı: «Retry-After», idempotentlik, sorğu limiti.
Cavab nümunəsi:json
HTTP/1. 1 202 Accepted
Location: /v1/withdrawals/req_9f2/status
Retry-After: 2
{
"request_id": "req_9f2", "state": "processing", "next_check_sec": 2
}
9) Isti yolda işi minimuma endirmək
Ağır şeyləri arxa plana çıxarın: transformasiyalar, aqreqasiyalar, bildirişlər, DWH-yə yazılar.
Cache və proyeksiyalar: tez-tez oxunan - qısa TTL və hadisə əlilliyi ilə cache-aside.
Batch-patterns: xarici zəngləri qruplaşdırın (məsələn, N ms-də bir dəfə provayder limitlərinin sorğusu).
Serializasiya: xidmətlərarası əlaqələr üçün sürətli codec (protobuf/msgpack); JSON yalnız edge.
10) DB nəzarət altında
Bağlantı hovuzları: yuxarı sərhədlər (nüvələr/IO əsasında), hovuz növbələri daxildir.
İndeks və plan: p95 explain + Auto Regression Plans test.
Vaxt sorğuları: qısa, 'statement _ timeout' (Postgres).
Hot rows/locks: açar, optimist bloklama (balans versiyası), «monolit» əməliyyat əvəzinə saga.
11) WebSocket/real-time
poçt məhdudlaşdırıcı: batched broadcast, max msgs/sec per connection.
Daxili backpressure: kapla gedən mesajların növbəsi; daşdıqda - drop low-priority.
Sticky-routing və PDB buraxılışlarında - reconnect fırtınasını artırmamaq üçün.
12) Təxmin etməmək üçün müşahidə
Metriklər (RED/USE + backpressure):- 'request _ rate', 'error _ ratio', 'latency _ p95/p99' marşrutları üzrə.
- `queue_depth`, `lag_seconds`, `consumer_inflight`, `retries_total`, `dlq_rate`.
- `backpressure_drops`, `admission_rejects`, `circuit_open`.
- Для БД: `connections_in_use/max`, `locks`, `slow_queries`.
- Tracks: span 'queue → worker → db/psp' 'operation _ id', 'partition', 'retry' etiketləri ilə.
- Log: struktur, 'trace _ id', PII olmadan; fərdi hadisələr «open/close circuit».
13) Yük altında test
sıçrayışlar üçün Open-model (arrivals/sec); Closed-model (VUs) seanslar üçün.
Profillər: qısa burst 60-120 s və soak 1-4 saat.
Nasazlıq inyeksiyaları: xarici API-ni + 200-500 ms-də yavaşlatın, p99/retraya/növbəyə baxın.
Yaşıl zonanın meyarları: 'queue _ lag', sabit p95, 'dlq _ rate ≈ 0'.
14) Təhlükəsizlik və etibarlılıq
TLS/mTLS üzrə növbələr, mesaj imzası, sxem nəzarəti (Avro/Protobuf + Schema Registry).
Idempotent producer (Kafka), haqlı olduğu yerdə exactly-once tx.
Xaos rejimi: vaxtaşırı asılılığı «atın» və deqradasiyaya baxın (circuit, fallback).
15) Konfiqurasiya «parçaları» nümunələri
Nginx/Envoy giriş Shaping:nginx limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;
server {
location /api/ {
limit_req zone=api burst=40 nodelay;
proxy_read_timeout 0. 6s; # qısa SLO proxy_connect_timeout 0. 2s;
}
}
RabbitMQ (prefetch):
basic. qos (prefetch_count = 32) # CPU/IO balans
Kafka consumer (Java fraqmenti):
java props. put(ConsumerConfig. MAX_POLL_RECORDS_CONFIG, 200);
props. put(ConsumerConfig. FETCH_MAX_BYTES_CONFIG, 5_000_000);
props. put(ConsumerConfig. MAX_POLL_INTERVAL_MS_CONFIG, 60_000);
16) Giriş çek siyahısı (prod-ready)
- Kritik yollar sinxron cavab və asenkron emal (SEDA) bölünür.
- Admission control və xarici asılılıq rəqabət limitləri.
- SLO-dan daha qısa vaxt; retrailer ≤ 2, eksponent və jitter ilə; Koalessinq.
- Circuit breaker + deqradasiya (cache/stab), half-open siyasəti.
- Növbələr/axınlar: prefetch/in-flight, DLQ, açar partiyalar.
- İdempotentlik (operation_id/Idempotency-Key), Outbox/Inbox, deduplication.
- Cache: cache-aside, qısa TTL + hadisə əlilliyi.
- BD: hovuz limitləri, statement_timeout, indekslər, anti-lock strategiyaları.
- WS: mesaj limitləri, batching, sticky-routing, PDB.
- Müşahidə: backpressure/queues/retries metrik, end-to-end treys, dashboard.
- Yük və imtina testləri (open + closed, burst + soak), yaşıl zonanın meyarları.
Xülasə
Sürətli geri dönüş «başqa bir cache etmək» deyil, idarə olunan bir axındır: giriş məhduddur, ağır - arxa plana, hər mərhələdə növbə və limitlər, retrajlar nadir və ağıllıdır və zəncirlər circuit breaker və idempotentlik ilə qorunur. Time-auts intizamı, müşahidə və müntəzəm stress testləri əlavə edin - və p95/p99 xarici provayderlərin bursları və şıltaqlıqları altında da yaşıl qalacaq.