Tiga Cara Menutup Sebuah Pesan
| Perintah | Arti | Nasib pesan |
|---|---|---|
basic.ack | Berhasil diproses | Dihapus dari queue |
basic.nack(requeue=true) | Gagal, coba lagi | Kembali ke queue |
basic.nack(requeue=false) | Gagal, jangan diulang | Ke DLX, atau dibuang |
basic.reject | Sama seperti nack, tapi satu pesan saja | Sesuai flag requeue |
Perbedaan nack dan reject: nack mendukung flag multiple untuk menutup banyak pesan sekaligus. Dalam praktik, nack hampir selalu yang dipakai.
requeue=true tanpa penundaan = poison message loopBila pemrosesan gagal karena payload memang rusak, mengembalikannya ke queue berarti ia akan langsung diambil lagi, gagal lagi, dikembalikan lagi — ribuan kali per detik.
pesan rusak → nack(requeue=true) → head of queue → ambil lagi
→ gagal lagi → nack lagi → ... CPU 100%, queue macet totalPesan itu juga kembali ke depan antrean, sehingga memblokir pesan sehat di belakangnya. Solusinya: requeue=false dengan DLX (bab 7), atau batas x-delivery-limit pada quorum queue.
Prefetch: Setelan Paling Berdampak yang Sering Dilewatkan
basic.qos(prefetch_count=N) membatasi berapa pesan boleh berstatus unacked pada satu konsumer. Tanpa ini, broker mendorong pesan sebanyak yang bisa ditampung jaringan.
prefetch = 0 (tanpa batas)
broker ──── 50.000 pesan ────> konsumer memori klien meledak
pembagian beban rusak
prefetch = 1
broker ──── 1 pesan ────> konsumer
<─── ack ─────────
paling adil, tetapi ada jeda jaringan pada setiap pesan
→ throughput rendah untuk tugas yang cepat
prefetch = 20
broker ──── 20 pesan ────> konsumer (pipeline terisi)
keseimbangan yang baik untuk mayoritas kasusTugas lambat, durasi bervariasi (mis. panggil API pihak ketiga, 2–30 detik)
→ prefetch = 1..5
Alasan: pembagian beban yang adil lebih berharga daripada throughput.
Prefetch besar membuat satu konsumer memegang pekerjaan
yang seharusnya dikerjakan konsumer lain yang sedang menganggur.
Tugas cepat dan seragam (mis. transformasi JSON, < 50 ms)
→ prefetch = 100..300
Alasan: latensi jaringan mendominasi; pipeline perlu tetap terisi.
Rumus awal yang berguna:
prefetch ≈ (waktu bolak-balik jaringan / waktu proses per pesan) + 1
lalu ukur dan sesuaikan.Prefetch Global vs Per Konsumer
channel.qos(prefetch, global=false) ← DEFAULT dan hampir selalu benar
batas berlaku PER KONSUMER pada channel itu
channel.qos(prefetch, global=true)
batas berlaku untuk SELURUH channel, dibagi semua konsumer di dalamnya
Contoh: 1 channel, 3 konsumer, prefetch 10
global=false → tiap konsumer boleh 10 unacked (total 30)
global=true → ketiganya berbagi jatah 10 (total 10)Siklus Redelivery
Pesan dikembalikan ke queue bila:
• konsumer memanggil nack/reject dengan requeue=true
• channel ditutup sebelum ack
• koneksi terputus (jaringan, restart aplikasi, deploy)
• konsumer dibatalkan sementara pesan masih unacked
Pesan yang dikirim ulang ditandai: redelivered = trueredelivered=true bukan penghitung percobaanFlag ini hanya bernilai benar atau salah — ia tidak memberi tahu berapa kali pesan sudah dicoba. Pesan yang gagal 500 kali punya flag yang sama dengan yang gagal sekali.
Untuk menghitung percobaan, gunakan salah satu:
- Quorum queue dengan
x-delivery-limit— broker menghitung sendiri, cara paling andal. - Header hitungan yang Anda kelola sendiri saat mem-publish ulang lewat DLX (bab 7).
Konsekuensi bagi Deployment
Saat konsumer di-deploy ulang, semua pesan unacked miliknya kembali ke queue dan diproses ulang oleh instance lain. Dengan prefetch 300 dan lima konsumer, satu deploy bisa berarti 1.500 pesan diproses dua kali.
let sedangMati = false;
process.on('SIGTERM', async () => {
sedangMati = true;
// 1. berhenti menerima pesan baru
await channel.cancel(consumerTag);
// 2. beri waktu pesan yang sedang diproses untuk selesai
await tungguSampaiSelesai({ timeoutMs: 25000 });
// 3. baru tutup
await channel.close();
await koneksi.close();
process.exit(0);
});Pasangkan dengan terminationGracePeriodSeconds di Kubernetes yang lebih besar dari timeout di atas, agar pod tidak dibunuh paksa di tengah pekerjaan.
Membaca Angka Unacked
rabbitmqctl list_queues name messages messages_ready messages_unacknowledged consumers| Pola angka | Artinya |
|---|---|
ready tinggi, unacked 0, consumers 0 | Tidak ada konsumer — aplikasi mati atau gagal connect |
ready tinggi, unacked = prefetch × konsumer | Konsumer ada tapi terlalu lambat — tambah konsumer |
unacked tinggi dan diam | Konsumer menggantung, lupa ack, atau deadlock |
ready naik-turun stabil | Sehat |