[RabbitMQ] Prefetch와 성능

dongbin_Shin·2022년 7월 7일
1

Prefetch란

Queue의 메시지를 Consumer의 메모리에 쌓아둘 수 있는 최대 메시지의 양이다.
만약 Prefetch = 250일 경우, RabbitMQ는 250개의 메시지까지 한번에 consumer의 메모리에 Push한다.
그 후 Consumer는 메모리에서 메시지를 하나씩 꺼내서 처리를 하게 된다.
prefetch 값에 따라 성능 차이가 생기므로 어플리케이션에 맞게 조정을 해야한다.

spring default prefetch 값은 250

Prefetch 값으로 인해 일어날 수 있는 문제 상황

예를 들어 총 500개의 메시지가 publish 됐을 경우,

  1. Consumer1과 Consumer2가 각각 250개씩의 메시지를 자신의 메모리에 가져간다.
  2. consumer는 메시지를 1개씩 처리
  3. 처리가 끝날 경우 자신의 메모리에서 메시지를 꺼내 처리한다.

이 경우에 어떤 상황이 발생할 수 있을지 생각해보자.
위의 상황에서 전체 처리 속도를 높이기 위해 consumer를 하나 더 등록했다고 가정하자.

  1. Consumer1이 먼저 Queue에서 메시지 250개를 메모리로 가져감
  2. Consumer2가 나머지 메시지 250개를 메모리로 가져감
  3. Queue에 남은 메시지가 없으므로 Consumer3는 가져갈 메시지가 없음

하지만 prefetch 값을 170으로 설정했다면,
consumer들은 각각 170, 170, 160개의 메시지를 가져가기 때문에 전체 처리 속도가 개선될 것이다.

이처럼 prefetch 값은 전체 성능에 많은 영향을 끼친다.

Prefetch Criteria

  • 메시지를 처리하는 처리 속도가 빠르고, 하나의 큐에 적은 consumer가 있으면 high
  • 메시지를 처리하는 처리 속도가 빠르고, 하나의 큐에 많은 consumer가 있으면 middle
  • 메시지를 처리하는 처리 속도가 느리면 1

위처럼 prefetch 값을 설정해야 전체 성능 저하가 없다.

메시지를 처리하는 속도가 느릴 경우, 메시지를 메모리에 먼저 올려놓고 처리하는 것은 비효율적이기 때문에 1로 설정한다.

prefetch 전략은 single과 multiple 중 선택할 수 있다.

Single Prefetch

어플리케이션 전체에서 동일한 Prefetch 값을 설정하는 방법이다.
application.yml에 다음과 같이 추가하면 된다.

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

Multiple Prefetch

Consumer 별로 다른 prefetch 값을 설정하는 방법이다.

먼저 prefetch 값을 설정하는 SimpleRabbitListenerContainerFactory 메소드가 있는 config 파일을 생성한다.

@Configuration
public class RabbitmqSchemaConfig {
	
    @Bean
    public RabbitListenerContainerFactory<SimpleMessageListenerContainer> prefetchOneContainerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
        var factory = new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        factory.setPrefetchCount(1); // prefetch 값을 설정하는 부분
            
        return factory;
    }
}

그 후 container를 사용할 listener에서 설정한 containerFactory를 선택해 사용한다.
-> containerFactory 옵션 변수에 SimpleRabbitListenerContainerFactory를 생성하는 @Configuration의 메서드 명을 입력하면 된다.
이처럼 입력하면 해당 listener만 prefetch 값을 조정할 수 있다.

@Service
public class TestConsumer {
	private static final Logger log = LoggerFactory.getLogger(TestConsumer.class);
    
    @RabbitListener(queues="q.test", concurrency="2", containerFactory="prefetchOneContainerFactory")
    public void listenTest(TestMessage message) {
    	log.info("message is {}", message);
    }
}

또는 application.yml 파일에서도 수정이 가능하다.

spring:
	rabbitmq:
    	listener:
        	direct:
            	prefetch: 600
            simple:
            	prefetch: 600

Reference

profile
멋있는 백엔드 개발자

0개의 댓글