รูปแบบหัวข้อ RabbitMQ แบบ Topic โดยใช้ประเภท TopicExchange แตกต่างจากรูปแบบการเส้นทาง (Direct) ในที่ว่าพารามิเตอร์การเส้นทางรองรับการจับคู่แบบพร้อมพรั่ง (fuzzy matching) เนื่องจากการจับคู่เส้นทางมีความยืดหยุ่นมากขึ้น จึงเป็นรูปแบบที่ใช้ที่พบบ่อยกว่า โครงสร้างอยู่ในแผนภูมิดังนี้:

RabbitMQ แบบ Topic Pattern

คำแนะนำ: ไม่ว่าจะใช้รูปแบบการทำงาน RabbitMQ แบบใด ความแตกต่างอยู่ที่ประเภทของ exchange ที่ใช้และพารามิเตอร์การเส้นทาง

1. บทชี้สอนพื้นฐาน

โปรดอ่านส่วนต่อไปนี้ก่อนเพื่อทำความเข้าใจความรู้ที่เกี่ยวข้อง:

2. การกำหนด Exchange แบบ Topic

ใน Spring AMQP, คลาสที่สอดคล้องกับ exchange แบบ Direct คือ TopicExchange เรากำหนด exchange ผ่านคลาสการกำหนดค่า Spring Boot

package com.tizi365.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueueConfig {
    @Bean
    public TopicExchange topic() {
        // กำหนด exchange
        // พารามิเตอร์คือชื่อของ exchange ซึ่งต้องเป็นเอกลักษณ์
        return new TopicExchange("tizi365.topic");
    }
}

คำแนะนำ: ทั้งผลิตของข้อความและผู้บริโภคข้อความต้องการ exchange

3. การส่งข้อความ

เราส่งข้อความไปยัง exchange และ exchange จะส่งข้อความไปยังคิวที่สอดคล้องกันตามกฎการเส้นทาง

package com.tizi365.rabbitmq.service;

import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class SendService {
    @Autowired
    private RabbitTemplate template;
    @Autowired
    private TopicExchange topic;

    // เพื่ออุปการะการเสาขความ, สามารถใช้งานงานตามกำหนดเวลาที่แนบเนี่ยวนี้เพื่อส่งข้อความทุกวินาที
    @Scheduled(fixedDelay = 1000, initialDelay = 1000)
    public void send() {
        // เนื้อหาข้อความ
        String message = "สวัสดี โลก!";
        // ส่งข้อความ
        // พารามิเตอร์แรกคือชื่อของ exchange
        // พารามิเตอร์ที่สองคือคีย์ของเส้นทาง และ Topic exchange ส่งข้อความไปยังคิวที่ตรงกับคีย์ของการเส้นทาง
        // พารามิเตอร์ที่สามคือเนื้อหาข้อความ รองรับประเภทใด ๆ ให้มีค่าพร้อมกันตรงกับการอัพเซอร์ไพล์ได้
        template.convertAndSend(topic.getName(), "www.tizi365.com", message);
        System.out.println("ส่งข้อความ: '" + message + "'");
    }
}

คำแนะนำ: ให้ใส่ใจกับตัวแปรพารามิเตอร์ที่สอง "www.tizi365.com" ใน convertAndSend method เนื่องจากมันเป็นพารามิเตอร์ที่สำคัญ

4. การรับข้อความ

4.1 กำหนดคิวและผูกแลกเจส

เพื่อรับข้อความจากคิว คุณต้องกำหนดคิวก่อน และผูกคิวกับแลกเจสเป้าหมาย ด้านล่างนี้ กำหนดคิวสองรูปแบบและผูกกับแลกเจสเดียวกัน

package com.tizi365.rabbitmq.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueueConfig {
    @Bean
    public TopicExchange topic() {
        // กำหนดแลกเจส
        // พารามิเตอร์คือชื่อแลกเจส ซึ่งต้องไม่ซ้ำกัน
        return new TopicExchange("tizi365.topic");
    }

    @Bean
    public Queue queue1() {
        // กำหนดคิว 1
        return new Queue("tizi365.topic.queue1");
    }

    @Bean
    public Queue queue2() {
        // กำหนดคิว 2
        return new Queue("tizi365.topic.queue2");
    }

    @Bean
    public Binding binding1(TopicExchange topic, Queue queue1) {
        // กำหนดความสัมพันธ์การผูก ผูกคิว 1 กับแลกเจสแบบ topic ด้วยรูทติงคีย์ของ: *.tizi365.com
        return BindingBuilder.bind(queue1).to(topic).with("*.tizi365.com");
    }

    @Bean
    public Binding binding2(TopicExchange topic, Queue queue2) {
        // กำหนดความสัมพันธ์การผูก ผูกคิว 2 กับแลกเจสแบบ topic ด้วยรูทติงคีย์ของ: *.baidu.com
        return BindingBuilder.bind(queue2).to(topic).with("*.baidu.com");
    }
}

คำแนะนำ: เมื่อผูกคิว 1 และคิว 2 กับแลกเจส รูทติงคีย์ที่กำหนดใช้ * (ดอกจัน) wildcard ซึ่งตรงกันกับคำศัพท์เดียว หากเปลี่ยนเป็น # (แฮช) จะตรงกันกับคำศัพท์หลายคำ

4.2 กำหนดผู้ฟังคิว

กำหนดผู้ฟังข้อความโดยใช้การประกาศ RabbitListener เพื่อรับข้อความจากคิวที่ระบุ

package com.tizi365.rabbitmq.listener;

import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

// ให้ Spring จัดการคลาสปัจจุบัน
@Component
public class DemoListener {
    // กำหนดผู้ฟัง ระบุคิวที่ต้องการฟังผ่านพารามิเตอร์ queues
    @RabbitListener(queues = "tizi365.topic.queue1")
    public void receive1(String msg) {
        System.out.println("ได้รับข้อความจากคิว 1: " + msg);
    }

    // กำหนดผู้ฟัง ระบุคิวที่ต้องการฟังผ่านพารามิเตอร์ queues
    @RabbitListener(queues = "tizi365.topic.queue2")
    public void receive2(String msg) {
        System.out.println("ได้รับข้อความจากคิว 2: " + msg);
    }
}

เนื่องจากเฉพาะคิว 1 มีรูทติงคีย์เป็น *.tizi365.com เมื่อผูกกับแลกเจส จะตรงกับข้อความที่มีรูทติงคีย์ (www.tizi365.com) ดังนั้น เฉพาะคิว 1 จะสามารถรับข้อความได้ ในขณะที่คิว 2 จะไม่ได้รับเนื่องจากรูทติงคีย์ที่ไม่ตรงกัน