Broker & Node #

Bagi sebagian pengembang yang baru mengenal middleware pesan, RabbitMQ sering kali dipandang secara sederhana sebagai sebuah “antrean” (queue) tempat menaruh pesan sementara waktu. Namun untuk merancang arsitektur sistem produksi yang tangguh, kita harus mengubah cara pandang tersebut secara mendasar. RabbitMQ adalah sebuah Broker pesan logis yang berjalan di atas satu atau beberapa Node fisik atau virtual. Memahami perbedaan, batasan, dan cara kerja hubungan antara abstraksi logis broker dengan runtime fisik node merupakan fondasi utama sebelum kita mengeksplorasi konsep kluster (clustering), replikasi antrean (quorum queues), atau pemulihan bencana (disaster recovery).

Entitas Logis: Anatomi Broker RabbitMQ #

Secara arsitektur, Broker adalah entitas logis yang bertanggung jawab untuk menerima, merutekan, menyangga (buffering), dan mengirimkan pesan dari produsen ke konsumen. Broker menyediakan antarmuka protokol komunikasi (seperti AMQP 0-9-1, AMQP 1.0, MQTT, atau STOMP) yang digunakan aplikasi kita untuk berinteraksi.

flowchart TD
    subgraph LogicalBroker ["Logical Broker Abstraction"]
        Ex["Exchange Routing Engine"]
        Binding["Binding Rules Table"]
        Q["Queue Management System"]
        Ex -->|"Route matching"| Binding
        Binding --> Q
    end
    
    P["Producer Client"] -->|"Publish via TCP"| Ex
    Q -->|"Push via TCP"| C["Consumer Client"]

Di dalam sebuah Broker, terdapat beberapa komponen logis yang saling terhubung:

  1. Exchange Routing Engine: Komponen pintar yang menganalisis metadata pesan masuk dan merutekannya ke antrean yang tepat berdasarkan aturan pencocokan (routing rules). Exchange itu sendiri tidak pernah menyimpan pesan sedikit pun; ia bertindak murni sebagai pengarah lalu lintas data.
  2. Binding Table: Kamus pemetaan yang mencatat hubungan antara exchange dengan antrean, berisi kunci pencocokan (routing keys) yang dikonfigurasi oleh pengembang.
  3. Queue Management System: Komponen yang bertugas menjaga state antrean, mengurutkan pesan (FIFO), melacak status konfirmasi pesan (ACK tracking), dan mengelola alokasi pengiriman ke konsumen yang aktif.
  4. Connection & Channel Tracker: Komponen yang melacak koneksi TCP yang aktif dan mengelola sub-koneksi logis (Channels) di dalamnya untuk menghemat handshake soket jaringan.

Broker adalah otak logis dari sistem pesan kita. Ia mengamankan kontrak pengiriman data antara produsen dan konsumen berjalan sesuai aturan tanpa memedulikan di mana data tersebut disimpan secara fisik pada perangkat keras.


Isolasi Logis: Konsep Virtual Hosts (Vhosts) #

Sebagai broker logis, RabbitMQ tidak hanya memisahkan routing melalui exchange dan queue, tetapi juga menyediakan fitur Virtual Hosts (Vhosts) untuk menciptakan partisi isolasi logis tingkat tinggi. Konsep vhost sangat mirip dengan konsep virtual machine pada server fisik atau virtual host pada web server Apache/Nginx.

Setiap vhost di dalam RabbitMQ bertindak sebagai sebuah broker mini yang mandiri:

  • Isolasi Nama: Antrean bernama order-queue dapat dibuat di vhost /payment dan vhost /shipping secara bersamaan tanpa saling mengganggu.
  • Isolasi Exchange dan Binding: Exchange dan aturan routing hanya berlaku di dalam vhost tempat mereka didefinisikan. Produsen tidak dapat mengirim pesan ke exchange yang berada di vhost berbeda secara langsung.
  • Keamanan dan Hak Akses: Kita dapat memberikan izin (permissions) kepada pengguna tertentu untuk melakukan konfigurasi, menulis (write), dan membaca (read) data hanya pada vhost tertentu (misalnya, tim logistik hanya memiliki akses ke vhost /logistics).

Secara fisik, seluruh vhost ini berjalan di atas node yang sama dan berbagi sumber daya CPU, memori, serta disk yang sama. Pemisahan vhost murni merupakan pemisahan logis di tingkat software RabbitMQ untuk mempermudah multi-tenancy dan pengorganisasian microservices yang besar.


Unit Fisik: Struktur Eksekusi Node RabbitMQ #

Jika Broker adalah konsep logisnya, maka Node adalah unit fisik pengeksekusinya. Node adalah satu instansi aplikasi runtime RabbitMQ yang berjalan di dalam satu unit sistem operasi — baik berupa server bare-metal, mesin virtual (VM), maupun kontainer Docker/Kubernetes.

Setiap Node RabbitMQ terdiri dari komponen fisik berikut:

flowchart TD
    subgraph Node["Node (rabbit@node-prod-01)"]
        subgraph VM["Erlang BEAM VM"]
            ConnProc["Connection Proc"]
            QueueProc["Queue Proc"]
        end
        subgraph Storage["Storage Directory"]
            Mnesia["Mnesia Metadata DB"]
            MsgStore["Message Store (persistent.rd)"]
            Config["Configuration: rabbitmq.conf"]
        end
        VM --- Storage
    end

1. Runtime Erlang BEAM VM #

Setiap node RabbitMQ berjalan di atas mesin virtual Erlang (BEAM VM). Erlang VM dirancang khusus untuk menangani konkurensi tingkat tinggi dengan jutaan proses ringan yang terisolasi secara mandiri. Hal ini memungkinkan satu node RabbitMQ mengelola ribuan antrean dan koneksi TCP secara bersamaan tanpa mengalami kebocoran memori.

2. Direktori Penyimpanan Node (Node Data Directory) #

Node memiliki lokasi penyimpanan lokal pada disk server yang menampung file-file berikut:

  • Mnesia Database: Database internal non-relasional bawaan Erlang yang digunakan untuk menyimpan metadata kluster, konfigurasi exchange, definisi antrean, kebijakan (policies), dan hak akses pengguna (permissions).
  • Message Store: Lokasi penyimpanan file biner tempat pesan-pesan persisten disimpan ke disk saat antrean penuh atau ketika produsen meminta keamanan data.
  • Queue Index Store: File indeks yang melacak lokasi fisik pesan di dalam antrean untuk mempercepat pembacaan data FIFO.
  • rabbitmq.conf: File konfigurasi utama untuk mengatur batas memori (watermark), port jaringan, konfigurasi keamanan TLS, dan optimasi kernel OS.

3. Identitas Node #

Setiap node memiliki nama unik yang wajib terdaftar dalam DNS jaringan. Nama node RabbitMQ memiliki format prefix@hostname, misalnya rabbit@node-prod-01. Jika hostname server berubah atau resolusi DNS gagal, node tersebut tidak akan dapat mengenali direktori penyimpanannya sendiri dan akan menolak untuk menyala.


Topologi Kluster: Bagaimana Node Berkolaborasi Membentuk Broker #

Ketika aplikasi kita tumbuh besar, satu node tunggal tidak akan mampu menampung seluruh beban lalu lintas data dan memberikan jaminan ketersediaan tinggi (High Availability). Di sinilah keajaiban RabbitMQ terwujud: kita dapat menghubungkan beberapa node fisik yang berbeda melalui jaringan untuk bertindak sebagai satu Logical Broker yang tunggal.

flowchart TD
    subgraph LogicalBrokerCluster ["Single Logical Broker (Cluster View)"]
        direction LR
        subgraph Node1 ["Node 1 (rabbit@host-01)"]
            M1["(Mnesia DB)"]
            Q1["Queue: billing-queue"]
        end
        subgraph Node2 ["Node 2 (rabbit@host-02)"]
            M2["(Mnesia DB)"]
            Q2["Queue: shipping-queue"]
        end
    end
    
    P1["Producer A"] -->|"Connect to Node 1"| Node1
    P2["Producer B"] -->|"Connect to Node 2"| Node2

Dalam sebuah kluster RabbitMQ:

  1. Replikasi Metadata: Setiap node di dalam kluster mereplikasi salinan database Mnesia secara penuh. Artinya, jika kita membuat exchange baru di Node 1, definisi exchange tersebut akan langsung tercatat secara instan di Node 2 dan Node 3. Aplikasi produsen dapat terhubung ke node mana saja di dalam kluster untuk mempublikasikan pesan ke exchange tersebut.
  2. Home Node untuk Classic Queue: Berbeda dengan metadata, Classic Queue (antrean klasik non-replikasi) secara fisik hanya hidup di satu node tertentu, yang disebut Home Node dari antrean tersebut. Jika antrean billing-queue dibuat di Node 1:
    • Seluruh pesan di dalam billing-queue secara fisik disimpan pada RAM/disk Node 1.
    • Jika produsen terhubung ke Node 2 dan mengirimkan pesan ke billing-queue, Node 2 secara otomatis akan mengalirkan pesan tersebut melalui jaringan internal Erlang ke Node 1 untuk disimpan.
    • If Node 1 mengalami downtime, antrean billing-queue tidak akan dapat diakses oleh konsumen meskipun Node 2 dan Node 3 masih menyala.
  3. Quorum Queues untuk High Availability: Untuk mengatasi kelemahan classic queue di atas, RabbitMQ menyediakan Quorum Queues yang mereplikasi data pesan fisik ke mayoritas node di dalam kluster menggunakan algoritma konsensus Raft, sehingga jika salah satu node mati, antrean tetap dapat diakses tanpa kehilangan data sedikit pun.

Siklus Hidup Node dan Proses Sinkronisasi Mnesia #

Mnesia adalah database sistem terdistribusi real-time bawaan Erlang yang menyimpan seluruh metadata dari kluster RabbitMQ. Untuk memahami bagaimana node berkolaborasi dalam kluster, kita harus memahami siklus hidup (lifecycle) node dan bagaimana sinkronisasi metadata Mnesia terjadi:

  1. Fase Start-Up (Inisialisasi): Saat node RabbitMQ dinyalakan, ia akan membaca file konfigurasi rabbitmq.conf untuk mendeteksi identitas node-nya (misal rabbit@rabbitmq-prod-01). Node kemudian menginisialisasi database Mnesia lokal di direktori disk.
  2. Penemuan Kluster (Cluster Discovery): Jika node dikonfigurasi untuk bergabung dengan kluster, ia akan menggunakan salah satu metode penemuan (seperti DNS, Consul, AWS EC2 tags, atau static host list) untuk menghubungi node aktif lainnya di dalam kluster.
  3. Sinkronisasi Skema Mnesia: Setelah berhasil menghubungi node lain, node baru tersebut akan menghentikan aplikasi pesan internalnya sementara waktu dan menyalin seluruh skema metadata Mnesia dari node aktif tersebut ke memori lokalnya.
  4. Verifikasi Versi: Kluster RabbitMQ mewajibkan semua node memiliki versi aplikasi Erlang dan RabbitMQ yang kompatibel. Jika terjadi ketidakcocokan versi major/minor, sinkronisasi skema Mnesia akan gagal dan node baru akan dikeluarkan dari kluster demi menjaga konsistensi data.

Distribusi Tanggung Jawab di Runtime: Proses Erlang Tingkat Node #

Erlang VM di setiap node RabbitMQ mendistribusikan beban kerja secara granular ke dalam proses-proses terisolasi yang disebut Erlang Processes. Hal ini menjamin bahwa kegagalan di satu komponen (misalnya bug pada parser protokol koneksi client) tidak akan pernah merusak komponen lain (seperti penyimpanan pesan ke disk).

Erlang VM menggunakan model Let It Crash (Biarkan Saja Crash) melalui struktur pohon pengawasan (Supervision Trees). Di dalam setiap node RabbitMQ, terdapat hierarki pengawas (Supervisors) yang bertugas memantau kesehatan proses pekerja (Worker Processes). Jika suatu proses pekerja (misalnya proses yang mengelola koneksi TCP ke produsen) mengalami error fatal akibat kehilangan koneksi internet tiba-tiba, pengawas akan membiarkan proses tersebut mati secara terisolasi. Pengawas kemudian akan membersihkan sumber daya soket yang tersisa dan membiarkan ribuan koneksi konsumen lain tetap berjalan secara paralel tanpa terpengaruh sedikit pun.

Berikut adalah bagan distribusi tanggung jawab proses Erlang di dalam satu node RabbitMQ:

  1. Connection Processes: Setiap kali client membuat koneksi TCP ke RabbitMQ, satu proses Erlang ringan dibuat khusus untuk menangani soket TCP tersebut. Proses ini bertugas membaca byte data dari jaringan, memvalidasi paket, dan mendekodekan protokol AMQP.
  2. Channel Processes: Di dalam satu koneksi, client dapat membuka beberapa channel logis secara paralel. Setiap channel dikelola oleh satu proses Erlang tersendiri yang menerima perintah dari Connection Process untuk mengeksekusi aksi bisnis (seperti mempublikasikan pesan atau membuat antrean).
  3. Queue Processes: Setiap antrean RabbitMQ dikelola oleh satu proses Erlang utama. Proses ini bertugas mengelola siklus hidup pesan di memori, menjadwalkan penulisan ke disk, melacak ACK konsumen, dan mendistribusikan pesan ke konsumen yang terikat.

Komunikasi antar proses Erlang ini dilakukan melalui mekanisme Message Passing bawaan runtime Erlang, baik antar proses di dalam satu node yang sama maupun lintas node fisik melalui soket jaringan kluster (menggunakan port internal Erlang, default 25672). Penggunaan protokol internal ini diamankan menggunakan kode rahasia yang disebut Erlang Cookie yang harus bernilai sama di seluruh node dalam kluster.


Perbandingan Single Node vs Multi-Node Cluster #

Untuk menentukan pilihan infrastruktur yang tepat bagi kebutuhan bisnis kita, berikut adalah tabel perbandingan komparatif karakteristik operasional antara konfigurasi Single Node dengan Multi-Node Cluster pada RabbitMQ:

AspekSingle NodeMulti-Node Cluster
Kemudahan DeploymentSangat Tinggi. Hanya butuh satu perintah Docker atau instalasi paket OS sederhana.Sedang hingga Tinggi. Memerlukan setup DNS, manajemen Erlang Cookie, dan konfigurasi jaringan.
Ketersediaan (Availability)Rendah. Jika mesin server mati, layanan pesan terhenti total.Sangat Tinggi. Kluster tetap berjalan selama mayoritas node aktif (menggunakan Quorum Queues).
Throughput PenulisanSangat Tinggi (Lokal). Tidak ada overhead latensi replikasi jaringan antar-node.Tergantung Tipe Antrean. Quorum queue memerlukan konfirmasi jaringan antar-node sebelum mengembalikan ACK.
Penggunaan Disk & RAMEfisien. Hanya menyimpan satu salinan data secara lokal.Lebih Tinggi. Replikasi data metadata Mnesia dan payload pesan memerlukan kapasitas tambahan di setiap node.
Biaya InfrastrukturSangat Rendah. Cukup satu instance server kecil.Lebih Tinggi. Membutuhkan minimal 3 node untuk kluster HA guna menghindari skenario split-brain.

Anti-Pattern vs Solusi: Resolusi Hostname yang Tidak Stabil Pada Lingkungan Kluster #

Mari kita pelajari salah satu kesalahan paling umum yang dilakukan oleh tim operasi dan pengembang saat men-deploy kluster RabbitMQ di lingkungan kontainer (seperti Docker atau Kubernetes) tanpa pemahaman yang benar mengenai karakteristik identitas node.

Kasus Anti-Pattern: Menggunakan Hostname Dinamis pada Kluster Kontainer #

Dalam skenario di bawah ini, pengembang menjalankan kontainer kluster RabbitMQ menggunakan konfigurasi Docker Compose bawaan tanpa mendefinisikan hostname yang statis. Akibatnya, setiap kali kontainer Docker di-restart, Docker engine secara acak memberikan hostname baru (misalnya rabbit@a3b8cd12f901).

# ANTI-PATTERN: Mengabaikan definisi hostname statis pada setup kluster kontainer
version: '3.8'
services:
  rabbitmq1:
    image: rabbitmq:3.12-management
    environment:
      - RABBITMQ_ERLANG_COOKIE=my_secret_cookie_shared
      # ✗ JANGAN: Tidak menyetel hostname statis.
      # Setiap restart akan membuat direktori data baru berbasis hostname acak Docker.
      # Database Mnesia kluster akan rusak karena node tidak mengenali nama lamanya.

Solusi Praktis: Mengonfigurasi Hostname Statis dan Resolusi Host Lokal #

Untuk menjamin node kluster dapat menyala kembali setelah crash dan membaca database Mnesia lamanya dengan aman, kita wajib menyetel hostname yang konsisten menggunakan opsi hostname pada konfigurasi kontainer dan mendaftarkannya pada file host lokal.

# BENAR: Menyetel hostname statis untuk menjaga integritas Mnesia DB
version: '3.8'
services:
  rabbitmq1:
    image: rabbitmq:3.12-management
    container_name: rabbitmq-prod-01
    hostname: rabbitmq-prod-01 # ✓ SOLUSI: Hostname statis yang konsisten
    environment:
      - RABBITMQ_ERLANG_COOKIE=my_secret_cookie_shared
      - RABBITMQ_NODENAME=rabbit@rabbitmq-prod-01 # ✓ SOLUSI: Nama node terikat ke hostname statis
    volumes:
      - rabbitmq_data1:/var/lib/rabbitmq/mnesia # ✓ SOLUSI: Mount direktori data persisten
    networks:
      - rabbitmq-net

networks:
  rabbitmq-net:
    driver: bridge

volumes:
  rabbitmq_data1:

Dengan konfigurasi ini, meskipun kontainer mati dan dinyalakan kembali, node akan selalu terlahir kembali dengan identitas rabbit@rabbitmq-prod-01 dan dapat membaca data Mnesia serta log transaksi sebelumnya secara sempurna tanpa menyebabkan status kluster menjadi corrupted.


Ringkasan #

  • Broker vs Node — Broker adalah abstraksi fungsional dari mesin perantara pesan, sedangkan Node adalah runtime fisik Erlang VM yang mengeksekusi broker tersebut di server.
  • Mnesia Metadata DB — Database internal non-relasional Erlang yang direplikasi secara otomatis ke seluruh node kluster untuk menyinkronkan definisi exchange dan antrean.
  • Home Node Dependency — Classic queue secara fisik hanya berada pada satu node tertentu. Kegagalan node tersebut akan membuat antrean tidak dapat diakses meskipun kluster masih hidup.
  • Static Hostname Requirement — Kebutuhan mutlak bagi node RabbitMQ untuk mempertahankan resolusi hostname jaringan yang stabil agar integritas data Mnesia DB tetap terjaga.

← Sebelumnya: Characteristic   Berikutnya: Single vs Cluster →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact