Messaging System dengan RabbitMQ & Spring Boot

Firman
9 min readAug 17, 2020

--

Messaging System

Pada artikel kali ini, saya akan menjelaskan sedikit materi mengenai RabbitMQ yang sempat saya implemementasikan di tim saya bekerja Mekari Innovator Lab.

Mungkin kita sudah sangat sering dengar tentang Messaging System atau Message Broker. Maksud dari Message di sini dapat kita artikan dengan sebuah Data.

Definisi Messaging System sendiri yakni sebuah mekanisme komunikasi dalam perpindahan message dari Application to Application. Biasanya Messaging System digunakan untuk berbagai jenis aplikasi terintegrasi, di mana aplikasi terintegrasi yakni terdiri dari beberapa aplikasi yang saling bertukar data atau mengirim dan mengambil data.

Tanpa Messaging System

Sebuah sistem di mana banyak aplikasi yang terintegrasi di dalamnya, maka tentu saja setiap aplikasi akan saling berhubungan dengan berbagai macam cara:

Pada gambaran di atas, App 1 mengirim data ke App 5, App 6, App 7.

Bagaimana jika untuk mengkoneksikan App 1 dengan App 5 adalah menggunakan File Transfer dalam bentuk CSV, dan mengkoneksi ke App 6 lainnya dengan JSON data format atau mungkin XML via API. Lalu pada koneksi ke App 7 menggunakan Database Link.

Di sini terdapat beberapa kelemahan pada sistem di atas yaitu:

  • Jenis data protokol terlalu banyak: database link, API, File transfer
  • Jenis format data pun terlalu banyak: JSON, CSV, XML
  • Dan dengan banyaknya integration point di atas kita perlu me-maintain semua protokol koneksi tersebut.

Lalu dengan Messaging System

Dalam mengatasi masalah-masalah di atas, kita dapat menggunakan Messaging System salah satunya dengan RabbitMQ.

Messaging System memungkinkan kita untuk memisahkan aplikasi dan komunikasi data.

Jadi semua Source System akan dikirim ke messaging system, sementara target system langsung mengambil data yang dibutuhkan dari Messaging System.

Dengan Messaging System memungkinkan kita dapat menentujan dari awal
apa saja standard format data yang akan digunakan di semua aplikasi. Jika kita menggunakan Json format, maka itu lah yang akan menjadi standar fortma data pada sistem tersebut dan semua aplikasi akan menggunakan standar yang sama.

Dengan Messaging System, kita tidak perlu memiliki banyak jenis Direct Communication, kita hanya akan menggunakan protokol yang sama yakni Messaging System Protocol.

Pada gambar di atas App 1 akan menjadi producer dan mengirim data ke Messaging System. Lalu App 5 menjadi consumer dan secara otomatis dapat mengambil data dari Messaging System jika data yang ditentukan memang tersedia. Dan App 1 pun dapat menerima data, sebaliknya App 5 dapat mengirim data.

RabbitMQ

Salah satu tool atau aplikasi untuk Messaging System yaitu RabbitMQ. RabbitMQ adalah sebuah Open Source Messaging System, dimana kita tidak perlu membayar untuk menggunakannya. Meski begitu RabbitMQ juga memiliki Enterprise Services.

RabbitMQ mampu untuk Queuing data atau menangani antrian data in real time yang dapat diproses nantinya.

Basic Concepts

Berikut skema konsep dasar RabbitMQ.

Pada terminologi RabbitMQ terdapat beberapa komponen:

  1. Publisher / Producer: yaitu aplikasi yang bertugas untuk mengirimkan data / message ke message lines RabbitMQ.
  2. Message Lines: message lines merupakan istilah pada RabbitMQ yang intinya sekumpulan dari Queue dan Exchange.
  3. Subscriber / Consumer: Aplikasi yang ter-registrasi atau ter-subscribe pada spesifik Queue tertentu dan dapat menerima data pada Queue yang di-subscribe, serta secara konsisten subscriber akan menerima message dari RabbitMQ.

Queue & Exchange

Dalam mekanisme Messaging System, kita harus memahami apa itu Queue dan apa itu Exchange.

  1. Queue: meurpakan sebuah baris atau line, yang menyimpan messages, sebelum messages di-consume untuk diproses lebih lanjut.
  2. Exchanges: merupakan routing message untuk queue. Exchange memiliki dua peran, yaitu menerima message dari Producer dan di sisi lain Exchange me-routing message ke spesifik queue yang dituju.
  3. Rotuing Key: sebuah address untuk memungkinkan Exchange mengetahui ke mana message harus di-Queue atau ke Queue yang mana yang akan dituju.
  4. Binding: yaitu berupa Queue name sebagai link antara koneksi Exchange ke Queue.

Tipe-Tipe Exchanges

Sebenarnya ada banyak tipe-tipe Exchange, namun pada artikel kali ini saya hanya menjelaskan tiga jenis Exchange yang sudah saya gunakan, diantaranya:

  1. Fanout Exchange
  2. Direct Exchange
  3. Topic Exchange

Fanout Exchange

Fanout Exchange memiliki fungsi untuk mem-brodcast single message untuk Multiple Queues. Fanout Exchange dapat mengirim data yang sama sebanyak tujuan yang diperlukan atau sebanyak aplikasi yang terdaftar (subscribe).

Pada skema di atas terdapat aplikasi Publisher yaitu POS System dan aplikasi Consumer yakni Sales System dan Accounting System. Dimana Sales System dan Accounting System membutuhkan data yang sama dari POS System.

Pada skema di atas terdapat ada dua Invoice Number INV-001 dan INV-002. Dengan mekanisme Fanout Exchange, maka dua Invoice tersebut akan disalin lalu dikirim kan ke aplikasi tujuan yang sudah ter-subscribe yakni Sales System dan Accounting System.

Direct Exchange

Jika pada Fanout Exchange kita mengirim messsages yang sama ke consumer, maka jika kita perlu mengirim messsages secara selektif ke Queue maka kita gunakan Direct Exchange.

Dengan Direct Exchange kita harus menulis Routing Key atau Address pada message yang akan dikirimkan dari producer ke RabbitMQ.

Lalu Direct Exchange akan mengirimkan message ke Queue berdasarkan Routing Key.

Pada skema di atas Payment App mejadi Producer dia mengirim data payments, di mana data tersebut terdiri dari:

  • payment method
  • payment type

Pada data tersebut ada dua tipe payment:

  • EDC
  • EWALLET

Maka pada Routing Key akan kita arahkan:

  • jika key = EDC, maka message akan di Queue ke Queue Bank
  • jika key = EWALLET, maka message akan di Queue ke Queue EWALLET

Lalu pada Consumer yang sudah ter-subscribe akan menerima data sesuai Queue yang di-subscribe. Di mana:

  • Bank App akan menerima payment type EDC
  • Ewallet App akan menerima payment type EWALLET

Topic

Sebelumnya sudah dijelaskan tentang Direct Exchange yang mampu merutekan message secara selektif sesuai kriteria yang ditentukan yakni “EDC” dan “EWALLET”.

Namun Direct Exchange hanya bisa dapat menangani message bedasarkan pada Single Criteria, yakni “EDC” dan “EWALLET”.

Skema Topic Exchange

Sedangkan pada Topic Exchange ini kita dapat me-routing dengan Multiple Criteria dari source type. Hal ini bisa terjadi karena pada Topic Exchange memungkinkan kita dapat menggunakan karakter Wildcard.

Topic Data Case

Pada skema di atas terdapat dua data. Data pertama sebagai berikut:

  • Name: Picture0
  • Type: jpg
  • Source: mobile
  • Size: small

Pada data kedua:

  • Name: Picture5
  • Type: svg
  • Source: web
  • Size: large

Di mana kedua data di atas berasal dari Publisher Upload System yang akan dikirim ke Consumers Image System dan Vector System.

Data yang akan masuk ke dalam Queue sesuai Routing Key dengan menggunakan karakter Willcard.

How to Create Exchange

  • Klik menu Exchanges
  • Isi “Name” dan pilih “Type”
  • Fields lain dapat dibiarkan seperti default

How to Create Queue

  • Klik menu Queues
  • Isi “Name”
  • Fields lain dapat dibiarkan seperti default

How to Bind Exchange and the Queues

Bind diperlukan untuk mengarahkan Link antara Exchange ke Queue.

  • Pertama tentukan Exchange yang ingin di-Binding, contonya “x.picture”. Penamaan Exchange atau pun Queue itu terserah pada kita sendiri, tidak ada ketentuan
  • Lalu lakukan Binding dengan mengisi “To Queue” yaitu Queue name yang digunakan contoh “q.picture.image”
  • Lalu isi “Routing Key” contoh “jpg”
  • Field Arguments dapat dibiarkan kosong.

Spring Boot : Dependencies & Properties

Pada Spring Boot berikut contoh dependency dan property RabbitMQ.

build.gradle
pom.xml
application.yml

Spring Boot : Producer (Type: Direct Exchange)

Spring Boot : Consumer

Consumer Image
Consumer Vector

RabbitMQ : Messages

Queues
Queue Detail for Q.Picture.Image

Spring Boot : Log Producer

Spring Boot : Log Consumer

Handling Exception on Consumer

Handling Exception/Error pada Consumer ada dua tipe biasa digunakan yaitu:

  • DLX (Dead Letter Exchange)
  • TTL (Time to Live)

DLX (Dead Letter Exchange)

Terkadang kita bisa menemukan message yang tidak bisa proses, contohnya message tersebut terkena throws execption. Spring boot sendiri secara default akan merequeue invalid message tersebut.

Dengan mekanisme DLX, Invalid message dapat ditampung di Queue lain, dan dapat di consume untuk consumer lain.

TTL (Time to Live)

Timeout pada RabbitMQ, disebut juga TTL atau time to live.

TTL memungkinkan untuk membuang Queue dalam waktu yang ditentukan, jika tidak ada consumer yang meng-consume message tersebut, dan message tersebut dapat juga ditampung di Queue yang lain, seperti mekanisme DLX.

Manual Acknowledge

Acknowledge atau Ack merupakan mekanisme untuk menandakan bahwa message tersebut sudah selesai diproses. Jika kita tidak melakukan Ack maka message yang error tidak akan hilang dari RabbitMQ dan akan dire-queue saat restar tserver.

Spring Boot secara default sebenarnya akan otomatis sudah melakukan Ack dan kita tidak perlu untuk melakukan Manual Ack.

Namun jika kita mendapat error Throws Exception, maka consumer akan meng-consume invalid message tersebut dengan infinite loop. Maka kita dapat menggunakan Reject atau Ack pada error tersebut. Jika di Reject makan error akan diarahkan ke Queue DLX jika kita menggunakan Error Handling, jika tidak maka Queue akan dihilangkan.

Contoh cara mengimplementasikan Manual Ack:

Update Application.yml
Basic Reject and Basic Ack

Retry Mechanism (when consume the Queue)

Mekanisme Retry adalah mengulang proses message consume jika terdapat error pada saat message sedang di proses pada aplikasi consumer.

Kita dapat mengkonfigurasikan mekanisme Retry sebagai berikut:

  • MAX-ATTEMPS = 5
    Jika terjadi error atau exception, maka message tersebut akan di-retry sebanyak total 5 kali re-try atau 5 kali consume.
  • INITIAL-INTERNAL =3s
    Tiga detik ini merupakan Interval waktu pada 5 kali re-try tersebut.
    contoh:
    - 1st-consume itu di menit ke : 02:47
    - 2nd-consume itu di menit ke : 02:50 (47+3s)
  • MULTIPLIER = 2
    Multiplier merupakan Interval waktu pada 5 kali re-try tersebut, jika sebelumnya 3 detik, maka karena menggunakan MULTIPLIER = 2, selanjutnya interval berikutnya dikalikan 2
    - 1st-consume itu di menit ke : 02:47
    - 2nd-consume itu di menit ke : 02:50 (47+3s = 50s)
    - 3rd-consume itu di menit ke : 02:56 (50+(3s*2) = 56s)
  • MAX-INTERVAL = 10s
    Sebelumnya INITIAL-INTERNAL 3 Detik,
    Lalu MULTIPLIER = 2,
    dan interval berikutnya 3s x 2 = 6s,
    Hasilnya 6s x 2 = 12,
    Maka yang seharusnya interval pada 4th-consume itu ditambah 12 detik.
    Namun, karena adanya MAX-INTERVAL = 10 detik
    Maka, 12 detik tadi akan digantikan dengan angka 10 detik, menjadi sebagai berikut :
    - 1st-consume itu di menit ke : 02:47
    - 2nd-consume itu di menit ke : 02:50 (47 + 3s)
    - 3rd-consume itu di menit ke : 02:56 (50 + (3s*2))
    - 4th-consume itu di menit ke : 03:06 (56 + 10)
    - 5th-consume itu di menit ke : 03:16 (66 + 10)

--

--