Backpressure Membatasi Pekerjaan Saat Consumer Tertinggal

Producer yang cepat dan consumer yang lebih lambat dapat berjalan bersama selama burst singkat jika buffer menyerap selisihnya. Susunan yang sama menjadi tidak stabil ketika perbedaan rate bertahan. Pekerjaan tertunda menumpuk, penggunaan memory naik, latency memanjang, dan item dapat kedaluwarsa sebelum sempat diproses consumer.

Backpressure mengubah kontrak antara kedua sisi. Alih-alih menerima pekerjaan tanpa memperhatikan kondisi downstream, sistem mengekspos kapasitas terbatas kepada producer. Ketika kapasitas itu habis, produksi berhenti sementara, admission ditolak, atau policy overload eksplisit lain mulai berlaku.

rate producer > rate consumer
        |
        v
 pekerjaan tertunda bertambah
        |
        v
 memory + queueing delay

dengan backpressure:

producer <-- kapasitas -- consumer

Properti utamanya adalah jumlah pekerjaan outstanding yang terbatas. Backpressure tidak membuat consumer lambat menjadi lebih cepat. Mekanisme ini mencegah komponen upstream mengubah perlambatan tersebut menjadi antrean tanpa batas.

Antrean adalah kapasitas, bukan solusi overload

Antrean berguna untuk meredam perbedaan sementara antara arrival rate dan completion rate. Consumer yang biasanya menangani 1.000 item per detik dapat menerima 1.300 item per detik untuk sesaat, lalu menghabiskan kelebihannya setelah burst berakhir.

Perbedaan rate yang menetap memiliki aritmetika lain. Jika arrival tetap 1.300 item per detik sementara completion bertahan di 1.000, backlog bertambah sekitar 300 item setiap detik.

pertumbuhan backlog = arrival rate - completion rate

1300 - 1000 = 300 item/detik

Antrean yang lebih besar hanya menunda kegagalan; selisih rate tetap ada. Dengan antrean bounded, saturasi menjadi kondisi yang dapat diamati dan memiliki respons yang ditentukan. Dengan antrean tanpa batas, overload dapat tersembunyi sampai tekanan memory, timeout, atau process failure menampakkannya jauh kemudian.

Kapasitas antrean karena itu sebaiknya mencerminkan budget operasional: berapa banyak pekerjaan tertunda yang masih berguna, berapa memory yang dipakai, dan berapa queueing delay yang dapat ditoleransi service.

Sinyal kapasitas dapat memiliki beberapa bentuk

Backpressure adalah hubungan kontrol, bukan satu API tertentu. Transport yang berbeda mengekspos kapasitas dalam bentuk berbeda.

Bounded channel di dalam process dapat memblokir sender ketika tidak ada slot. Protokol stream dapat memberikan receive window terbatas. Message consumer dapat membatasi jumlah delivery yang belum di-acknowledge. API asynchronous dapat mengembalikan future yang baru selesai ketika receiver memiliki ruang.

credits = 32

kirim item -> credits = 31
kirim item -> credits = 30
...
consumer selesai -> credits += 1

Flow control berbasis credit membuat batas tersebut eksplisit. Producer hanya boleh memiliki operasi in-flight sebanyak credit yang tersedia. Pengembalian satu credit berarti kapasitas downstream tersedia kembali.

Blocking merupakan representasi lain dari constraint yang sama, tetapi konsekuensinya bergantung pada execution model. Memblokir dedicated worker mungkin dapat diterima. Memblokir event loop dapat menghentikan pekerjaan lain yang tidak terkait. Mekanisme kapasitas harus sesuai dengan scheduler dan concurrency model di sekitarnya.

Backpressure perlu merambat cukup jauh ke upstream

Bounded queue lokal hanya melindungi komponen yang memilikinya. Jika service upstream terus menerima request ke antrean lain yang tidak terbatas, backlog hanya berpindah tempat.

Pertimbangkan jalur request dengan tiga tahap:

client -> API -> worker -> database

Jika database melambat, worker mencapai batas concurrency atau antreannya. API kemudian perlu melihat kapasitas worker yang berkurang. Jika API juga mencapai batasnya, client memerlukan respons overload eksplisit atau admission yang secara alami melambat. Tanpa propagasi, setiap layer dapat menumpuk reservoir pekerjaan tertunda yang tersembunyi.

Propagasi tidak mengharuskan setiap layer memakai mekanisme yang sama. Worker dapat mengekspos bounded channel yang penuh, API dapat mengembalikan status overload, dan client dapat memakai retry terbatas dengan backoff. Hal yang penting adalah kelangkaan kapasitas downstream pada akhirnya mengurangi admission upstream.

Demand berbasis pull membuat boundary lebih eksplisit

Interface push sering dimulai dengan producer yang menentukan kapan data dikirim. Interface pull membalik kontrol tersebut: consumer meminta pekerjaan ketika memiliki kapasitas.

consumer: minta 8
producer: kirim maksimal 8
consumer: proses
consumer: minta 8 lagi

Model ini secara alami membatasi delivery outstanding jika jumlah request ditegakkan dengan benar. Pola tersebut terutama berguna pada streaming pipeline, tempat setiap tahap dapat mengiklankan demand kepada tahap sebelumnya.

Sistem push dapat memberikan kontrol setara melalui acknowledgement, credit, bounded mailbox, atau operasi send yang menunggu kapasitas. Pembeda pentingnya bukan push atau pull semata. Yang menentukan adalah apakah kemajuan producer tetap terkait dengan kapasitas downstream yang finite.

Ukuran buffer menetapkan budget latency sekaligus memory

Panjang antrean yang hanya dinyatakan sebagai jumlah item dapat menyembunyikan biaya yang terlihat oleh user. Jika consumer menyelesaikan 100 item per detik, 1.000 item dalam antrean mewakili sekitar sepuluh detik queueing time sebelum memperhitungkan variasi processing.

perkiraan queue delay = queued items / completion rate

1000 / 100 per detik = 10 detik

Estimasi itu sengaja sederhana, tetapi menunjukkan constraint desain yang penting. Pekerjaan dengan deadline dua detik hampir tidak bernilai jika berada di belakang backlog sepuluh detik.

Admission dapat memakai umur atau deadline selain jumlah item. Pekerjaan yang sudah kedaluwarsa sebaiknya dikeluarkan sebelum memakai processing capacity yang langka. Priority queue memerlukan perhatian serupa: lane prioritas tinggi dapat melindungi pekerjaan mendesak, sedangkan kelas prioritas tanpa batas dapat membuat traffic biasa tidak pernah mendapat giliran.

Cancellation harus mengembalikan kapasitas

Accounting backpressure gagal jika pekerjaan yang sudah ditinggalkan tetap menahan slot atau credit. Request yang timeout, stream yang dibatalkan, client yang terputus, atau consumer yang gagal harus mengembalikan kapasitas untuk pekerjaan yang tidak lagi selesai melalui jalur normal.

Hal ini terutama penting ketika kapasitas direpresentasikan sebagai permit. Setiap acquisition yang berhasil memerlukan release path untuk success, error, timeout, dan cancellation.

acquire permit
try:
    process item
finally:
    release permit

Skema credit terdistribusi juga memerlukan semantic recovery untuk koneksi yang hilang. Sender tidak dapat menganggap credit dari session lama tetap valid setelah reconnect kecuali protokol memang menetapkan perilaku tersebut.

Backpressure dan load shedding menangani masalah yang berdekatan

Backpressure meminta upstream melambat atau berhenti menerima pekerjaan baru ketika kapasitas sudah terpakai. Load shedding sengaja menolak pekerjaan yang tidak dapat dilayani dalam budget operasi sistem. Keduanya saling melengkapi, bukan saling menggantikan.

Batch pipeline mungkin dapat menoleransi waiting dan meneruskan pressure melalui bounded queue. API interaktif memiliki ruang tunggu yang lebih kecil, sehingga tercapainya admission bound sebaiknya menghasilkan respons overload dengan cepat. Streaming transport dapat menghentikan read sementara sampai ruang buffer tersedia lagi.

Tindakan yang tepat bergantung pada apakah waiting masih mempertahankan nilai pekerjaan. Jika penundaan membuat item tidak lagi berguna, rejection path yang bounded sering lebih baik daripada antrean yang lebih dalam.

Telemetry perlu mengekspos pressure boundary

Throughput saja tidak dapat menunjukkan apakah pipeline mendekati saturasi. Sinyal yang berguna mencakup queue depth, queue age, credit yang tersedia, durasi blocked send, admission yang ditolak, pekerjaan in-flight, completion rate, dan jumlah cancellation.

queue_depth=480
queue_capacity=500
oldest_item_ms=1750
in_flight=64
blocked_send_ms=38
admission=rejected

Queue depth memerlukan konteks. Antrean pada 90 persen kapasitas selama lima milidetik ketika burst berbeda dari antrean yang bertahan di sana selama beberapa menit. Age sering memperlihatkan pressure berkepanjangan dengan lebih langsung karena menunjukkan berapa lama pekerjaan yang diterima sudah menunggu.

Backpressure efektif ketika capacity boundary sesuai dengan resource yang dapat mengalami saturasi dan ketika sinyal tersebut mencapai producer yang menciptakan demand. Bounded buffer, credit eksplisit, accounting yang aman terhadap cancellation, dan perilaku overload yang terlihat mengubah perlambatan downstream menjadi kondisi terkontrol alih-alih kegagalan yang hanya ditunda.