Backpressure Mencegah Producer Cepat Membanjiri Consumer Lambat
Pipeline stabil selama pekerjaan meninggalkan setiap tahap dengan laju yang kurang lebih seimbang dengan laju masuk dalam rentang waktu yang relevan. Ketika producer dapat mengirim pekerjaan lebih cepat daripada kemampuan consumer menyelesaikannya, selisih tersebut harus menumpuk di suatu tempat.
Antrean tanpa batas membuat penumpukan itu mudah tersembunyi. Request terus diterima, producer tampak sehat, dan consumer tetap bekerja. Sementara itu, pekerjaan dalam antrean memakai memori dan semakin tua sebelum dieksekusi. Backpressure mengubah saturation downstream menjadi sinyal upstream sebelum backlog berubah menjadi kegagalan.
Perbedaan laju berubah menjadi pekerjaan tersimpan
Misalkan producer menghasilkan 1.000 job per detik sementara consumer hanya mampu mempertahankan 700:
arrival rate = 1000 jobs/s
service rate = 700 jobs/s
backlog growth = 300 jobs/sSetelah satu menit, antrean bertambah 18.000 job jika laju tersebut bertahan. Antrean yang lebih besar tidak mengubah service rate. Antrean hanya menyediakan ruang tambahan untuk menampung selisih laju.
Burst singkat berbeda. Buffer terbatas dapat menyerap variasi sementara jika consumer kemudian memiliki kapasitas cadangan yang cukup untuk mengurasnya. Persoalan rekayasanya bukan keberadaan antrean, melainkan penerimaan pekerjaan melebihi jumlah yang dapat diproses dalam batas resource dan latency yang ditetapkan.
Backpressure meneruskan sinyal kapasitas ke upstream
Channel terbatas membuat saturation terlihat jelas:
producer -> [ queue: capacity 1000 ] -> consumer
|
penuh
|
block, perlambat, atau tolakSetelah antrean mencapai limit, producer tidak dapat terus berjalan pada laju yang sama tanpa keputusan kebijakan. Bergantung pada workload, producer dapat menunggu kapasitas, menurunkan laju kirim, menolak pekerjaan baru, membuang pekerjaan berprioritas rendah, atau meminta pengirim eksternal melakukan retry kemudian.
Sifat pentingnya adalah feedback. Komponen yang membuat pekerjaan menerima bukti bahwa tahap berikutnya sedang tidak mampu menerima tambahan beban.
Blocking berguna hanya jika tekanan dapat diteruskan
Memblokir producer merupakan bentuk backpressure langsung, tetapi cara ini hanya efektif jika producer memang dapat berhenti dengan aman.
Pipeline streaming dengan channel in-memory terbatas sering dapat menangguhkan task upstream sampai consumer membebaskan slot:
await queue.put(item)Wait tersebut mencegah pertumbuhan antrean lokal. Namun, mekanisme itu tidak otomatis melindungi seluruh sistem. Jika task yang terblokir memegang koneksi langka, lock, transaction, atau worker yang diperlukan untuk progres lain, blocking dapat memindahkan saturation ke resource lain.
Tekanan perlu memiliki jalur kembali menuju titik yang benar-benar dapat mengurangi admission. Pada request server, titik tersebut dapat berupa request boundary. Pada message system, titiknya dapat berupa consumer prefetch atau partition intake. Pada batch pipeline, titiknya dapat berupa tahap yang menjadwalkan unit pekerjaan baru.
Antrean terbatas memperlihatkan overload lebih awal
Antrean tanpa batas sering mengubah overload menjadi kegagalan tertunda. Penggunaan memori naik perlahan, queueing delay membesar, deadline berakhir setelah pekerjaan telanjur memakai resource, dan recovery berlangsung lebih lama karena pekerjaan lama masih tertinggal.
Antrean terbatas memberi sistem backlog budget yang finite:
in flight <= worker capacity
queued <= queue capacity
age <= useful deadlineKetika budget tersebut habis, menolak pekerjaan dapat lebih aman daripada menerimanya. Response overload yang cepat memberi caller kesempatan menerapkan retry, fallback, atau shedding tanpa menunggu di belakang pekerjaan yang sudah terlalu tua untuk berguna.
Karena itu, queue capacity sebaiknya terkait dengan service time dan queueing delay yang dapat diterima, bukan dipilih hanya berdasarkan memori yang tersedia.
Traffic retry dapat merusak sinyal
Backpressure kehilangan manfaat jika rejection langsung menciptakan traffic tambahan.
Perhatikan client yang mengulang setiap request yang ditolak tanpa jeda:
overload -> reject -> immediate retry -> more overloadAntrean terbatas tetap melindungi memori, tetapi sistem di sekitarnya dapat menghabiskan CPU, bandwidth jaringan, dan kapasitas koneksi untuk memproses attempt yang peluang admission-nya kecil.
Retry memerlukan batas tersendiri. Exponential backoff, jitter, retry budget, deadline, dan petunjuk server seperti Retry-After dapat mengurangi tekanan retry yang tersinkronisasi. Idempotency tetap merupakan kebutuhan terpisah ketika operasi yang diulang mungkin sudah menghasilkan efek.
Flow berbasis pull membuat demand eksplisit
Sebagian interface mengekspresikan backpressure dengan membiarkan consumer meminta pekerjaan, bukan membiarkan producer terus melakukan push tanpa batas.
Worker pool dapat mengambil job berikutnya hanya ketika worker tersedia. Stream protocol dapat memakai credit atau window yang mewakili jumlah data yang siap diterima receiver. Database cursor dapat mengambil row secara batch alih-alih memuat seluruh result set sekaligus.
Mekanismenya berbeda, tetapi invariant-nya serupa:
outstanding work <= advertised capacityCredit harus sesuai dengan kapasitas downstream yang nyata. Mengiklankan window besar lalu menyimpan kelebihan data dalam buffer tanpa batas hanya memindahkan lokasi antrean.
Backpressure dan rate limiting melindungi boundary yang berbeda
Rate limiting biasanya membatasi traffic berdasarkan kebijakan yang dikonfigurasi: request per detik, byte per detik, atau operasi per tenant. Backpressure bereaksi terhadap kapasitas yang tersedia pada jalur pemrosesan.
Sebuah service dapat memerlukan keduanya. Rate limit per tenant dapat mencegah satu client mendominasi admission, sedangkan concurrency limit downstream dan antrean terbatas bereaksi ketika database atau worker pool mengalami saturation.
Rate limit statis saja tidak dapat mewakili setiap slowdown saat runtime. Backpressure menyediakan sinyal kapasitas lokal yang tidak tersedia dari kuota tetap.
Metrik perlu menampilkan tekanan sebelum kegagalan
Telemetry yang berguna mencakup:
queue depth
queue capacity
oldest item age
enqueue wait duration
admission rejection count
consumer throughput
producer arrival rate
in-flight work
end-to-end latencyQueue depth tanpa capacity sulit ditafsirkan. Depth 500 dapat ringan bagi satu pipeline dan kritis bagi pipeline lain. Oldest item age sering lebih berguna karena menghubungkan backlog langsung dengan latency.
Rasio antara arrival rate dan completion rate juga penting. Antrean penuh ketika completion mulai mengejar dapat bersifat sementara; antrean yang terus bertambah saat arrival bertahan di atas completion menunjukkan overload yang berlanjut.
Test perlu membuat consumer lambat secara terkendali
Test terarah dapat menahan consumer sementara producer tetap aktif:
set queue capacity to N
pause or slow consumer
submit more than N items
verify admission follows the configured policy
verify memory remains bounded
resume consumer
verify backlog drainsTest juga perlu memeriksa cancellation dan deadline. Pekerjaan yang timeout saat menunggu harus melepaskan permit dan queue slot dengan benar, atau mekanisme kontrol dapat kehilangan kapasitas setelah overload awal berakhir.
Backpressure tidak menciptakan kapasitas pemrosesan. Mekanisme ini membuat kekurangan kapasitas terlihat cukup awal agar sistem berhenti menumpuk pekerjaan yang tidak mampu dilayani. Buffer terbatas, aturan admission eksplisit, dan sinyal kapasitas menjaga perbedaan laju producer-consumer sementara agar tidak berubah menjadi penggunaan memori tanpa batas dan queueing delay yang terus membesar.