Backpressure Nedir? Sistemleri Aşırı Yükten Koruma
Producer, consumer'dan daha hızlı veri ürettiğinde ne olur? Bellek taşar mı? Sistem çöker mi? Backpressure ile veri akışını kontrol edin, tüketicilerin kapasitesine göre üretimi düzenleyin.
Problem
Producer: 10.000 mesaj/saniye ──→ Consumer: 1.000 mesaj/saniye
Sonuç:
0s: Buffer: 0
1s: Buffer: 9.000
10s: Buffer: 90.000
60s: Buffer: 540.000 → OutOfMemory! 💥
Backpressure Stratejileri
1. Drop (At)
Tüketici yetişemezse fazla mesajları at:
Producer ──→ [Buffer: 100] ──→ Consumer
↓ (taşma)
🗑️ Drop
Kullanım: Sensör verileri, log streaming (kayıp kabul edilebilir)
2. Buffer (Tamponla)
Mesajları sınırlı bir kuyrukta beklet:
Producer ──→ [Buffer: 10.000 max] ──→ Consumer
(dolunca producer bekler)
3. Throttle (Yavaşlat)
Producer'ın hızını sınırla:
// Producer'ı yavaşlat
async function produce(items: Item[]) {
for (const item of items) {
await queue.push(item);
if (queue.size() > HIGH_WATERMARK) {
await sleep(100); // Yavaşla
}
}
}
4. Pull-Based (Çek)
Consumer ne kadar işleyebiliyorsa o kadar ister:
Consumer: "10 mesaj ver" ──→ Producer
Producer: [10 mesaj] ──→ Consumer
Consumer: (işle) ... "20 mesaj daha ver" ──→ Producer
Reactive Streams (Pull-Based)
// RxJS ile backpressure
import { Observable, bufferCount, concatMap, delay } from 'rxjs';
const fastProducer$ = new Observable(subscriber => {
for (let i = 0; i < 100000; i++) {
subscriber.next(i);
}
});
fastProducer$.pipe(
bufferCount(100), // 100'lü grupla
concatMap(batch => // Sıralı işle
processBatch(batch).pipe(
delay(50) // Her batch arasında 50ms bekle
)
)
).subscribe();
Node.js Stream Backpressure
const readable = fs.createReadStream('large-file.csv');
const writable = fs.createWriteStream('output.csv');
readable.on('data', (chunk) => {
const canWrite = writable.write(chunk);
if (!canWrite) {
readable.pause(); // Backpressure: okumayı durdur
writable.once('drain', () => {
readable.resume(); // Yazar hazır, okumaya devam
});
}
});
Kafka'da Backpressure
Consumer Group:
max.poll.records: 500 → Her seferde en fazla 500 mesaj
max.poll.interval.ms: 300000 → 5 dakikada işlenmezse rebalance
Consumer yetişemiyorsa:
1. Consumer sayısını artır (partition sayısına kadar)
2. max.poll.records'u düşür
3. İşleme süresini optimize et
Watermark Stratejisi
Buffer kapasitesi: 10.000
High Watermark (8.000): → Producer'ı yavaşlat
Low Watermark (2.000): → Producer'ı tekrar hızlandır
┌─── High WM ───┐
Buffer: ████████░░░░░░░░░░░░░░
└─── Low WM ────┘
Gerçek Dünya Örnekleri
| Sistem | Backpressure | |--------|-------------| | TCP | Receive window (flow control) | | Node.js Streams | pause/resume, drain event | | Kafka | Consumer lag, poll config | | RxJS | buffer, throttle, sample | | gRPC | Flow control frames |
Best Practices
- Asla sınırsız buffer kullanmayın — Bellek taşmasına yol açar
- Watermark kullanın — High/low watermark ile akışı düzenleyin
- Monitoring — Buffer doluluk oranını ve consumer lag'ı izleyin
- Graceful degradation — Aşırı yükte kaliteli düşürme
- Pull-based tercih edin — Consumer kendi hızını kontrol etsin
- Alerting — Buffer %80'e ulaştığında alarm
Sonuç
Backpressure, veri akış sistemlerinin güvenilirliği için kritiktir. Producer ve consumer hız farkını yönetmezseniz, sistem kaçınılmaz olarak çöker. Doğru strateji ile hem veri kaybını hem de sistem çöküşünü önleyin.
Backpressure ve reactive patterns'ı LabLudus platformunda öğrenin.