[RabbitMQ] Prefetch

반응형

이번 글에서는 RabbitMQ의 Prefetch에 대해 알아보겠습니다.

1. Prefetch란?

Queue의 메세지를 Consumer의 메모리에 쌓아놓을 수 있는 최대 메세지의 양 입니다.

예를 들어 Prefetch가 250일 경우, RabbitMQ는 250개의 메세지까지 한번에 Listener의 메모리에 Push합니다. 그뒤 Consumer는 메모리에서 하나씩 메세지를 꺼내서 처리하게 됩니다. 이러한 Prefetch 값은 각 어플리케이션 환경에 맞도록 조정할 필요가 있습니다.

예를 들어 아래의 그림에서 총 500개의 메세지가 발행됬다고 가정해보겠습니다. 이후 Prefetch가 250인 Consumer1과 Consumer2가 각각 250개씩 본인들의 메모리에 메시지를 가져갑니다. 그뒤 각각의 Consumer는 1개씩 메시지를 처리하고 다음 메세지는 본인들의 메모리에서 가져옵니다.

image.png

😅 이 경우 발생할 수 있는 문제는 다음과 같습니다.

만약 위의 상황에서 전체 메세지 처리 속도를 높이기위해 Consumer를 하나더 등록해 사용하기로 가정했다고 해보겠습니다. 이를 위해 Listener에 Consumer3를 추가했습니다. 이제 Consumer3는 쌓여있는 메세지를 나눠가져 처리할 수 있을까요?

답은 'No' 입니다.

위에서 설명했듯이 Prefetch가 250이기 때문에 이미 모든 메세지는 Consumer1과 Consumer2의 메모리에 분배되었습니다. 따라서 Consumer3가 가져갈 수 있는 메세지가 더이상 Queue에 남아있지 않습니다. 따라서 이경우 Consumer3는 Idle한 상태로 남아있게 됩니다.

이와 같이 Prefetch 설정값은 전체 App의 성능에 많은 영향을 끼칩니다. Prefetch 값을 설정하는 criteria는 아래와 같습니다.

image.png

위의 표를 해석해보면..

메시지를 처리하는 process time이 fast일 경우에는 middle ~ high의 prefetch 를 사용하면됩니다. 반면에 process time이 slow일 경우에는 반드시 prefetch를 1로 설정해야 전체 app 성능저하가 없습니다. process time이 느릴 경우에는 많은 메시지를 메모리에 먼저 올려놓고 처리할 이유가 전혀 없기 때문입니다.

위와 같은 Prefetch 전략은 Single / Multiple 중 선택해 사용할 수 있습니다.

2. Single Prefetch

APP 전체에서 동일한 Prefetch 값을 설정하기위해선 application.yml에 아래와 같은 항목을 추가하면 됩니다.

spring:
  rabbitmq:
    listener:
      simple:
        prefetch: [PREFETCH_COUNT]

3. Multiple Prefetch

각각의 Listener 별로 다른 Prefetch를 사용하기위해선 아래와 같이 설정할 수 있습니다.

image.png

먼저 @Configuration을 선언한 config 파일에서 prefetch를 값을 설정한 SimpleRabbitListenerContainerFactory을 아래와 같이 선언합니다.

@Configuration
public class RabbitmqSchemaConfig {

    @Bean
    public RabbitListenerContainerFactory<SimpleMessageListenerContainer> prefetchOneContainerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory)
     {
        var factory = new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        factory.setPrefetchCount(1);

        return factory;
    }
}

다음으로 해당 Container를 사용할 Listener에서 아래와 같이 ContainerFactory를 선택해 사용할 수 있습니다.

@Service
public class DummyPrefetchConsumer {

    private static final Logger log = LoggerFactory.getLogger(DummyPrefetchConsumer.class);

    @RabbitListener(queues = "q.dummy", concurrency = "2", containerFactory = "prefetchOneContainerFactory")
    public void listenDummy(DummyMessage message){
        log.info("message is {} ", message);
    }
}

위처럼 containerFactory 변수에 SimpleRabbitListenerContainerFactory을 생성하는 @Configuration의 메서드를 입력하면 됩니다. 위와 같이 입력하면 해당 Listener만 Prefecth 값을 조정 할 수 있습니다.


참고 자료 : https://www.udemy.com/course/rabbitmq-java-spring-boot-for-system-integration/


추천서적

 

RabbitMQ 따라잡기:AMQP 기반의 오픈소스 메시지 브로커

COUPANG

www.coupang.com

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음


반응형

댓글

Designed by JB FACTORY