Queue Terbatas Mengubah Overload Menjadi Penolakan Eksplisit

Queue dapat menyerap lonjakan singkat ketika request datang lebih cepat daripada kemampuan worker menyelesaikannya. Buffer tersebut berguna selama tetap berfungsi sebagai buffer. Jika producer terus dapat menambahkan pekerjaan tanpa batas tetap, overload berkepanjangan mengubah queue menjadi tumpukan request yang dapat menunggu lama setelah hasilnya tidak lagi berguna.

Queue terbatas mengubah bentuk kegagalan itu. Queue menerima pekerjaan yang menunggu sampai kapasitas yang ditetapkan, lalu menolak admission tambahan sampai tersedia ruang. Service tetap mengalami overload, tetapi overload muncul sebagai keputusan kontrol yang eksplisit, bukan pertumbuhan memory dan waktu tunggu tanpa batas.

Queue menyimpan delay sekaligus pekerjaan

Bayangkan worker pool yang mampu menyelesaikan 500 job per detik sementara producer mengirim 700 job per detik. Backlog bertambah sekitar 200 job setiap detik selama laju tersebut bertahan.

arrival rate = 700 job/s
service rate = 500 job/s
backlog growth = 200 job/s

Setelah 30 detik, sekitar 6.000 job tambahan menunggu, tanpa memperhitungkan variasi waktu eksekusi dan kedatangan. Jika queue tidak memiliki batas praktis, diterimanya satu job baru tidak memberi kepastian kapan job itu dapat mulai diproses.

Masalah tetap ada walaupun setiap item queue berukuran kecil. Request yang menunggu dapat menahan payload, tracing state, cancellation handle, promise, file descriptor, atau referensi ke object graph yang lebih besar. Queue juga menciptakan latency yang tidak terlihat jika monitoring hanya mencatat waktu eksekusi worker.

Kapasitas tetap membuat delay yang tersimpan itu dapat diukur. Kapasitas bukan sekadar pengaturan memory; kapasitas merupakan bagian dari admission policy service.

Kapasitas queue perlu terkait dengan waktu tunggu yang masih berguna

Ukuran queue yang dipilih hanya berdasarkan memory tersedia dapat jauh lebih besar daripada kemampuan service mengurasnya sebelum caller kehilangan kepentingan terhadap hasil. Titik awal yang lebih berguna menghubungkan kapasitas dengan throughput dan interval queueing yang dapat diterima.

Jika pool menyelesaikan sekitar 500 job per detik dan rancangan mengizinkan residence time queue paling lama 200 ms dalam rentang operasi target, perkiraan kasar kapasitasnya:

500 job/s * 0.2 s = 100 job

Perhitungan tersebut bukan rumus universal untuk menentukan ukuran. Service time bervariasi, utilisasi worker berubah, traffic datang dalam burst, dan sebuah queue dapat melayani beberapa kelas pekerjaan. Namun, perhitungan itu memberi pertanyaan konkret: berapa banyak pekerjaan yang masih bernilai ketika worker tersedia?

Pengukuran percentile lebih informatif daripada satu nilai rata-rata jika distribusi service time lebar. Kapasitas juga memerlukan ruang untuk burst normal tanpa berubah menjadi reservoir bagi overload berkepanjangan.

Queue penuh memerlukan hasil admission yang jelas

Saat queue mencapai batas, producer memerlukan perilaku deterministik. Pilihan umum mencakup penolakan langsung, menunggu slot dalam waktu singkat yang dibatasi, atau mengganti item berdasarkan policy yang memang dirancang untuk workload tertentu.

Untuk service request-response, penolakan langsung sering lebih tepat daripada diam-diam menunggu di belakang backlog yang sudah melewati latency budget yang berguna. Protocol dapat mengembalikan hasil overload seperti HTTP 503 Service Unavailable jika status tersebut sesuai dengan semantics kegagalan. Client kemudian dapat menerapkan deadline dan retry policy miliknya.

Menunggu slot secara terbatas dapat sesuai ketika contention singkat merupakan kondisi normal, tetapi penantian itu juga memerlukan deadline. Menunggu tanpa batas untuk masuk ke queue terbatas hanya memindahkan queue tanpa batas ke titik admission.

Membuang item yang sudah ada memerlukan semantics yang lebih kuat. Mengganti pekerjaan lama dengan pekerjaan baru dapat sesuai untuk telemetry atau workload refresh ketika hanya state terbaru yang penting. Kebijakan tersebut tidak aman untuk command yang mewakili kewajiban durable kecuali protocol di sekitarnya secara eksplisit mengizinkan kehilangan.

Backpressure dan penolakan menangani boundary yang berbeda

Backpressure meminta producer mengurangi laju produksi saat consumer tidak mampu mengimbanginya. Penolakan menyatakan bahwa unit pekerjaan tertentu tidak diterima. Sebuah sistem dapat menggunakan keduanya.

Di dalam satu process, bounded channel dapat secara alami memblokir producer sampai kapasitas kembali tersedia. Melintasi network, server sering tidak dapat secara langsung memperlambat setiap producer upstream. Server dapat berhenti membaca sementara, membatasi concurrent stream, mengiklankan flow-control limit dari protocol, atau menolak request agar caller menerima signal yang dapat ditindaklanjuti.

Backpressure paling efektif ketika signal mencapai komponen yang mampu mengurangi demand. Jika intermediary terus menerima pekerjaan ke buffer miliknya yang tidak terbatas, pressure diserap alih-alih diteruskan, dan boundary overload hanya berpindah ke upstream.

Penolakan eksplisit tetap diperlukan ketika demand tidak dapat diperlambat secukupnya. Sistem dengan kapasitas terbatas memerlukan titik untuk menolak pekerjaan baru.

Retry dapat menggagalkan perlindungan overload

Penolakan mengurangi pekerjaan yang diterima hanya jika caller tidak langsung menciptakan kembali load yang ditolak. Client yang melakukan retry pada setiap 503 tanpa jeda dapat mengubah satu request yang ditolak menjadi beberapa arrival tambahan.

Karena itu, retry policy merupakan bagian dari model kapasitas yang sama. Exponential backoff, jitter, batas attempt, dan deadline end-to-end dapat mengurangi sinkronisasi sekaligus membatasi retry amplification. Server dapat memberi retry hint jika protocol mendukungnya, tetapi client tetap memerlukan batas lokal.

Tidak setiap penolakan dapat di-retry. Queue penuh akibat saturasi sementara berbeda dari input tidak valid atau kegagalan authorization permanen. Klasifikasi error perlu mempertahankan perbedaan tersebut agar retry middleware tidak memperlakukan setiap hasil non-success sebagai attempt berikutnya.

Ketika banyak client memakai dependency yang sama, delay acak menjadi penting. Interval retry tetap yang identik dapat menyelaraskan caller menjadi gelombang traffic berulang tepat ketika service mulai pulih.

Batas queue perlu berada dekat resource langka

Queue melindungi kapasitas paling baik ketika ditempatkan pada resource yang concurrency-nya harus dibatasi. Database connection pool, worker pool yang berat di CPU, allowance API eksternal, dan executor per tenant dapat memerlukan admission limit terpisah.

Satu queue global dapat menyembunyikan resource mana yang sedang jenuh. Request yang tertahan pada dependency lambat dapat memakai semua worker slot walaupun CPU masih idle. Bulkhead atau concurrency limit terpisah dapat mengisolasi jalur tersebut, dengan penantian terbatas pada setiap boundary yang relevan.

Beberapa queue juga membawa pilihan scheduling. Workload bervolume tinggi dapat membuat pekerjaan bervolume rendah kelaparan jika keduanya bersaing melalui jalur first-in, first-out yang ketat. Limit per kelas atau per tenant dapat mempertahankan kapasitas untuk kelas traffic berbeda selama policy-nya eksplisit dan dapat diamati.

Jumlah seluruh limit lokal tetap penting. Membuat queue besar pada setiap layer dapat melipatgandakan pekerjaan yang tertahan sepanjang request path. Batas perlu membentuk capacity policy end-to-end, bukan membuat setiap buffer sebesar mungkin secara terpisah.

Cancellation perlu mengeluarkan pekerjaan basi dari queue

Request dapat kehilangan kegunaan sebelum mencapai worker. Caller dapat disconnect, deadline dapat habis, atau update yang lebih baru dapat menggantikannya. Membiarkan item tersebut berada di queue membuang execution slot pada masa mendatang.

Queue yang sadar cancellation dapat menghapus atau menandai entry basi sebelum service dimulai. Jika penghapusan langsung mahal, worker dapat memeriksa cancellation segera setelah dequeue dan melewati eksekusi. Kedua pendekatan sebaiknya menghindari pekerjaan mahal untuk item yang hasilnya sudah tidak memiliki penerima.

Residence time queue harus dihitung terhadap deadline end-to-end yang sama dengan eksekusi. Memulai operasi 500 ms setelah request sudah menunggu 900 ms tidak sesuai dengan request budget 1 detik.

Metric perlu membedakan penolakan saat admission, expiry selama berada di queue, cancellation sebelum eksekusi, dan kegagalan setelah eksekusi dimulai. Hasil-hasil tersebut menunjukkan kondisi kapasitas dan dependency yang berbeda.

Metric queue memperlihatkan saturasi sebelum memory

Queue depth berguna, tetapi tidak lengkap. Depth 80 dapat sehat untuk satu pool dan parah untuk pool lain. Queue residence time menunjukkan delay yang benar-benar dialami pekerjaan yang diterima.

Signal yang berguna mencakup current depth, capacity, admission rate, rejection rate, dequeue rate, percentile residence time queue, jumlah worker aktif, execution duration, dan cancellation count. Perbandingan arrival rate dengan completion rate menunjukkan apakah backlog sedang berkurang atau bertambah.

Queue yang terus berada dekat kapasitas sementara rejection meningkat sedang beroperasi pada admission boundary. Queue yang dangkal sementara worker tetap jenuh dapat menunjukkan bahwa limit menjalankan fungsinya. Queue yang tumbuh sementara completion rate turun dapat mengarah pada dependency slowdown, bukan sekadar kenaikan traffic.

Pengukuran tersebut juga membuat perubahan kapasitas dapat diuji. Menaikkan limit dapat mengurangi rejection jangka pendek sambil meningkatkan tail latency dan pekerjaan yang tertahan. Trade-off itu terlihat hanya jika rejection dan waktu tunggu diamati bersama.

Queue dengan batas tetap menjadikan overload keputusan policy

Tidak ada kapasitas queue yang dapat membuat demand berkepanjangan menghilang. Jika arrival terus melampaui service capacity cukup lama, sistem pada akhirnya harus memperlambat producer, menolak pekerjaan, membuang demand berprioritas rendah, atau menambah service capacity yang efektif.

Queue tanpa batas menunda keputusan tersebut sambil menumpuk kewajiban. Queue terbatas menempatkan keputusan pada boundary yang diketahui dan memberi service nilai maksimum stabil untuk pekerjaan yang menunggu. Pekerjaan engineering berikutnya adalah memilih kapasitas, perilaku admission, kontrak retry, dan scheduling policy yang sesuai dengan masa guna serta kepentingan workload.

Boundary tersebut tidak menggantikan concurrency limit, deadline, circuit breaker, atau load shedding. Queue terbatas memberi kontrol tersebut tempat yang finite untuk bekerja: pekerjaan diterima dalam waiting budget yang diketahui atau ditolak sebelum backlog menjadi sumber kegagalan.