RabbitMQ의 라우팅 패턴 (직접 모드)은 DirectExchange 유형의 교환을 사용합니다. 발행-구독 패턴과의 차이점은 Direct 교환은 완전히 일치하는 라우팅 매개변수를 가진 큐로 메시지를 전달합니다. 아키텍처는 아래 이미지와 같습니다:

RabbitMQ Direct Mode

팁: RabbitMQ 작업 모드에 상관없이 차이점은 사용된 교환 유형과 라우팅 매개변수에 있습니다.

1. 필수 자습서

다음 섹션들을 읽어 관련 지식을 이해해주세요:

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는 어떠한 메시지도 수신하지 않습니다.