Menu Bar

Kata Mutiara

"Keberhasilan merupakan tetesan dari jeri-payah perjuangan, luka, pengorbanan dan hal-hal yang mengejutkan. Kegagalan merupakan tetesan dari kemalasan, kebekuan, kelemahan, kehinaan dan kerendahan"

ANIMASI TULISAN BERJALAN

Showing posts with label Routing. Show all posts
Showing posts with label Routing. Show all posts

Monday, January 27, 2025

Work Queue hingga RPC: Membongkar Pola Messaging RabbitMQ dengan Contoh

 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:

  1. Produser (sender) mengirimkan pesan ke antrian.
  2. Beberapa konsumer (worker) mengambil pesan dari antrian.
  3. 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:

  1. 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;

@Component
public class TaskProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendTask(String task) {
        rabbitTemplate.convertAndSend("task_queue", task);
        System.out.println("Task Sent: " + task);
    }
}
  1. Receiver (Worker): Setiap worker mendengarkan antrian yang sama dan memproses pesan.
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public 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);
    }
}
  1. 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:

  1. Produser mengirim pesan ke FanoutExchange.
  2. Exchange mendistribusikan pesan ke semua antrian yang terhubung.
  3. Semua konsumer menerima pesan.

Studi Kasus:

Skenario:

Sebuah sistem pengumuman mengirimkan pesan ke semua layanan seperti email, SMS, dan notifikasi aplikasi.

Konfigurasi:

  1. Sender: Mengirimkan pesan ke exchange.
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class AnnouncementSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendAnnouncement(String message) {
        rabbitTemplate.convertAndSend("announcement_exchange", "", message);
        System.out.println("Announcement Sent: " + message);
    }
}
  1. Receivers: Email, SMS, dan aplikasi memiliki antrian masing-masing.
@Component
public 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:

  1. Produser mengirimkan pesan dengan routing key ke DirectExchange.
  2. 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:

  1. Sender: Mengirim pesan log berdasarkan level.
@Component
public 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);
    }
}
  1. Receiver: Setiap konsumer hanya menerima pesan untuk level tertentu.
@Component
public 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:

  1. Produser mengirimkan pesan dengan routing key ke TopicExchange.
  2. 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:

  1. Sender: Mengirimkan data dengan routing key.
@Component
public 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);
    }
}
  1. Receiver: Menerima pesan berdasarkan wilayah.
@Component
public 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:

  1. Klien mengirim pesan ke antrian permintaan.
  2. Server memproses pesan dan mengirim respons ke antrian balasan.
  3. Klien menerima respons.

Studi Kasus:

Skenario:

Sebuah sistem menghitung faktorial angka yang diminta oleh klien.

Konfigurasi:

  1. Client: Mengirim permintaan dan menunggu respons.
@Component
public class FactorialClient {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public int requestFactorial(int number) {
        return (Integer) rabbitTemplate.convertSendAndReceive("rpc_queue", number);
    }
}
  1. Server: Memproses permintaan dan mengirim respons.
@Component
public 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.

iklan

iklan