รูปแบบหัวข้อ RabbitMQ แบบ Topic โดยใช้ประเภท TopicExchange แตกต่างจากรูปแบบการเส้นทาง (Direct) ในที่ว่าพารามิเตอร์การเส้นทางรองรับการจับคู่แบบพร้อมพรั่ง (fuzzy matching) เนื่องจากการจับคู่เส้นทางมีความยืดหยุ่นมากขึ้น จึงเป็นรูปแบบที่ใช้ที่พบบ่อยกว่า โครงสร้างอยู่ในแผนภูมิดังนี้:
คำแนะนำ: ไม่ว่าจะใช้รูปแบบการทำงาน RabbitMQ แบบใด ความแตกต่างอยู่ที่ประเภทของ exchange ที่ใช้และพารามิเตอร์การเส้นทาง
1. บทชี้สอนพื้นฐาน
โปรดอ่านส่วนต่อไปนี้ก่อนเพื่อทำความเข้าใจความรู้ที่เกี่ยวข้อง:
- หลักการพื้นฐาน RabbitMQ
- หลักการของรูปแบบ Topic ของ RabbitMQ
- คำแนะนำเร็วสำหรับ Java กับ RabbitMQ (ต้องอ่านเพราะส่วนที่เหลือจะไม่ทำซ้ำโค้ด แค่แสดงโค้ดสำคัญเท่านั้น)
- ส่วนของการเผยแพร่แบบสับซ์ไทสำหรับ Java กับ RabbitMQ (ต้องอ่านเพราะไวยากรณ์โค้ดเกือบเหมือนกัน แต่แลกเปลี่ยนประเภทและพารามิเตอร์การเส้นทางเท่านั้น)
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 จะไม่ได้รับเนื่องจากรูทติงคีย์ที่ไม่ตรงกัน