RabbitMQ의 라우팅 패턴 (직접 모드)은 DirectExchange 유형의 교환을 사용합니다. 발행-구독 패턴과의 차이점은 Direct 교환은 완전히 일치하는 라우팅 매개변수를 가진 큐로 메시지를 전달합니다. 아키텍처는 아래 이미지와 같습니다:
팁: RabbitMQ 작업 모드에 상관없이 차이점은 사용된 교환 유형과 라우팅 매개변수에 있습니다.
1. 필수 자습서
다음 섹션들을 읽어 관련 지식을 이해해주세요:
- RabbitMQ 기본 개념
- RabbitMQ 라우팅 모드 원리
- RabbitMQ와 Java의 빠른 시작 (이후 섹션은 코드를 중복하지 않고 핵심 코드만 표시하므로 필독)
- RabbitMQ와 Java의 발행-구독 패턴 (이후 섹션은 코드 구조가 거의 같으므로 교환 유형과 라우팅 매개변수만 다름으로 필독)
2. Direct 교환 정의하기
Spring AMQP에서 Direct 교환에 해당하는 클래스는 DirectExchange입니다. 우리는 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 DirectExchange direct() {
// 교환 정의
// 매개변수는 고유해야 하는 교환 이름
return new DirectExchange("tizi365.direct");
}
}
팁: 메시지 생성자와 소비자는 모두 교환을 필요로 합니다.
3. 메시지 전송하기
우리는 메시지를 교환에 보내고, 그 후 라우팅 규칙에 따라 메시지를 해당 큐로 전달합니다.
package com.tizi365.rabbitmq.service;
import org.springframework.amqp.core.DirectExchange;
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 DirectExchange direct;
// 데모를 위해 예약된 작업을 사용하여 매초 메시지를 보냅니다
@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void send() {
// 메시지 내용
String message = "안녕, 세계!";
// 메시지를 보냅니다
// 첫 번째 매개변수는 교환 이름
// 두 번째 매개변수는 라우팅 키입니다. 직접 교환의 경우 메시지는 라우팅 키가 "tizi365"와 일치하는 큐로 전달됩니다.
// 세 번째 매개변수는 메시지 내용으로, 직렬화될 수 있는 모든 유형을 지원합니다
template.convertAndSend(direct.getName(), "tizi365", message);
System.out.println("메시지 '" + message + "'를 보냈습니다");
}
}
팁: convertAndSend 메서드의 두 번째 매개변수에 주의하십시오. 이것은 중요한 매개변수입니다.
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 DirectExchange direct() {
// 익스체인지 정의
// 매개변수는 고유해야 하는 익스체인지 이름
return new DirectExchange("tizi365.direct");
}
@Bean
public Queue queue1() {
// 큐 1 정의
return new Queue("tizi365.direct.queue1");
}
@Bean
public Queue queue2() {
// 큐 2 정의
return new Queue("tizi365.direct.queue2");
}
@Bean
public Binding binding1(DirectExchange direct, Queue queue1) {
// 바인딩 정의: 큐 1을 "tizi365" 라우팅 키로 익스체인지에 바인딩하여야 함
// 라우팅 키가 "tizi365"와 일치할 때 익스체인지는 메시지를 큐 1에 전달함
return BindingBuilder.bind(queue1).to(direct).with("tizi365");
}
@Bean
public Binding binding2(DirectExchange direct, Queue queue2) {
// 바인딩 정의: 큐 2를 "baidu" 라우팅 키로 익스체인지에 바인딩하여야 함
// 라우팅 키가 "baidu"와 일치할 때 익스체인지는 메시지를 큐 2에 전달함
return BindingBuilder.bind(queue2).to(direct).with("baidu");
}
}
4.2 큐 리스너 정의
RabbitListener 주석을 사용하여 특정 큐에서 메시지를 소비하는 메시지 리스너를 정의합니다.
package com.tizi365.rabbitmq.listener;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
// Spring이 현재 클래스를 관리하도록 함
@Component
public class DemoListener {
// 큐 1에서 메시지를 수신하는 리스너 정의
@RabbitListener(queues = "tizi365.direct.queue1")
public void receive1(String msg) {
System.out.println("큐1에서 메시지 수신: " + msg);
}
// 큐 2에서 메시지를 수신하는 리스너 정의
@RabbitListener(queues = "tizi365.direct.queue2")
public void receive2(String msg) {
System.out.println("큐2에서 메시지 수신: " + msg);
}
}
라우팅 키가 "tizi365"인 큐 1만이 익스체인지에 바인딩될 때 메시지를 수신할 수 있습니다. 라우팅 키가 일치하지 않기 때문에 큐 2는 어떠한 메시지도 수신하지 않습니다.