RabbitMQ: Penjelasan dan Studi Kasus Detail
RabbitMQ adalah message broker yang digunakan untuk berkomunikasi antar aplikasi melalui antrian pesan. Ia mendukung berbagai pola messaging seperti Work Queue, Publish/Subscribe, Routing, Topics, dan RPC. Berikut penjelasan detail dan studi kasus masing-masing pola:
1. Work Queue
Tujuan:
- Membagi pekerjaan secara adil ke beberapa worker (pekerja).
- Ideal untuk sistem yang membutuhkan load balancing.
Cara Kerja:
- Produser (sender) mengirimkan pesan ke antrian.
- Beberapa konsumer (worker) mengambil pesan dari antrian.
- Pesan hanya diproses oleh satu worker, memastikan tidak ada duplikasi.
Studi Kasus:
Skenario:
Sebuah sistem memproses data laporan harian, dan pekerja harus membagi tugas secara merata.
Konfigurasi:
- Sender:
Mengirimkan pesan ke antrian
task_queue
.
import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;
@Componentpublic class TaskProducer { @Autowired private RabbitTemplate rabbitTemplate;
public void sendTask(String task) { rabbitTemplate.convertAndSend("task_queue", task); System.out.println("Task Sent: " + task); }}
- Receiver (Worker): Setiap worker mendengarkan antrian yang sama dan memproses pesan.
import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;
@Componentpublic class TaskWorker {
@RabbitListener(queues = "task_queue") public void receiveTask(String task) { System.out.println("Processing Task: " + task); // Simulate processing time try { Thread.sleep(1000); } catch (InterruptedException ignored) {} System.out.println("Task Done: " + task); }}
- Hasil: Jika 10 tugas dikirim ke antrian, dan ada 2 worker, tugas akan dibagi rata, 5 tugas masing-masing.
2. Publish/Subscribe
Tujuan:
- Mengirimkan pesan ke banyak konsumer melalui sebuah exchange.
- Ideal untuk notifikasi atau broadcast.
Cara Kerja:
- Produser mengirim pesan ke
FanoutExchange
. - Exchange mendistribusikan pesan ke semua antrian yang terhubung.
- Semua konsumer menerima pesan.
Studi Kasus:
Skenario:
Sebuah sistem pengumuman mengirimkan pesan ke semua layanan seperti email, SMS, dan notifikasi aplikasi.
Konfigurasi:
- Sender: Mengirimkan pesan ke exchange.
import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;
@Componentpublic class AnnouncementSender { @Autowired private RabbitTemplate rabbitTemplate;
public void sendAnnouncement(String message) { rabbitTemplate.convertAndSend("announcement_exchange", "", message); System.out.println("Announcement Sent: " + message); }}
- Receivers: Email, SMS, dan aplikasi memiliki antrian masing-masing.
@Componentpublic class NotificationReceiver {
@RabbitListener(queues = "email_queue") public void receiveEmail(String message) { System.out.println("Email Notification: " + message); }
@RabbitListener(queues = "sms_queue") public void receiveSMS(String message) { System.out.println("SMS Notification: " + message); }}
3. Routing
Tujuan:
- Mengirim pesan berdasarkan routing key ke antrian tertentu.
- Ideal untuk sistem yang hanya memproses jenis pesan tertentu.
Cara Kerja:
- Produser mengirimkan pesan dengan routing key ke
DirectExchange
. - Exchange meneruskan pesan ke antrian yang cocok dengan routing key.
Studi Kasus:
Skenario:
Sebuah sistem log memiliki tiga level: INFO, WARN, dan ERROR. Pesan didistribusikan ke antrian sesuai level.
Konfigurasi:
- Sender: Mengirim pesan log berdasarkan level.
@Componentpublic class LogSender { @Autowired private RabbitTemplate rabbitTemplate;
public void sendLog(String level, String message) { rabbitTemplate.convertAndSend("logs_exchange", level, message); System.out.println("Log Sent: [" + level + "] " + message); }}
- Receiver: Setiap konsumer hanya menerima pesan untuk level tertentu.
@Componentpublic class LogReceiver {
@RabbitListener(queues = "error_queue") public void receiveError(String message) { System.out.println("ERROR Log: " + message); }
@RabbitListener(queues = "info_queue") public void receiveInfo(String message) { System.out.println("INFO Log: " + message); }}
4. Topics
Tujuan:
- Mengirim pesan berdasarkan pattern matching di routing key.
- Ideal untuk sistem yang membutuhkan pengelompokan pesan fleksibel.
Cara Kerja:
- Produser mengirimkan pesan dengan routing key ke
TopicExchange
. - Exchange meneruskan pesan ke antrian sesuai pola binding key.
Studi Kasus:
Skenario:
Sebuah sistem cuaca mengirimkan data cuaca regional. Konsumer hanya mendengarkan data untuk wilayah tertentu.
Konfigurasi:
- Sender: Mengirimkan data dengan routing key.
@Componentpublic class WeatherPublisher {
@Autowired private RabbitTemplate rabbitTemplate;
public void sendWeatherUpdate(String region, String update) { String routingKey = "weather." + region; rabbitTemplate.convertAndSend("weather_exchange", routingKey, update); System.out.println("Weather Update Sent: [" + region + "] " + update); }}
- Receiver: Menerima pesan berdasarkan wilayah.
@Componentpublic class WeatherReceiver {
@RabbitListener(queues = "weather_north_queue") public void receiveNorthWeather(String message) { System.out.println("North Region Weather: " + message); }}
5. RPC (Remote Procedure Call)
Tujuan:
- Mengimplementasikan komunikasi sinkron, di mana klien menunggu respons dari server.
Cara Kerja:
- Klien mengirim pesan ke antrian permintaan.
- Server memproses pesan dan mengirim respons ke antrian balasan.
- Klien menerima respons.
Studi Kasus:
Skenario:
Sebuah sistem menghitung faktorial angka yang diminta oleh klien.
Konfigurasi:
- Client: Mengirim permintaan dan menunggu respons.
@Componentpublic class FactorialClient { @Autowired private RabbitTemplate rabbitTemplate;
public int requestFactorial(int number) { return (Integer) rabbitTemplate.convertSendAndReceive("rpc_queue", number); }}
- Server: Memproses permintaan dan mengirim respons.
@Componentpublic class FactorialServer {
@RabbitListener(queues = "rpc_queue") public int calculateFactorial(int number) { int result = 1; for (int i = 1; i <= number; i++) { result *= i; } System.out.println("Calculated Factorial: " + result); return result; }}
Kesimpulan:
RabbitMQ mendukung berbagai pola komunikasi yang fleksibel:
- Work Queue: Load balancing tugas.
- Publish/Subscribe: Broadcast pesan ke banyak konsumer.
- Routing: Mengarahkan pesan berdasarkan kunci tertentu.
- Topics: Pencocokan pesan fleksibel dengan pola.
- RPC: Permintaan dan respons sinkron.
Dengan RabbitMQ, kita dapat membangun sistem terdistribusi yang efisien dan dapat diskalakan.