Free Lines Arrow
본문 바로가기
Message Queue/RabbitMQ

[RabbitMQ] Work Queues

by skahn1215 2022. 10. 3.
728x90
반응형

Work Queue

  • 여러 작업 자들에게 시간이 많이 걸리는 작업을 분배 시키는데 사용 할 대기열 큐를 만든다.
  • 리소스의 집약 적인 작업을 즉시 수행 하지 않도록 한다.
  • 그리고 작업들이 완료될때 까지 기다리는 것을 피하게 한다.
  • 백그라운드에서 작업을 처리하는 작업자는 작업들을 꺼내고 잡을 수행한다.
  • 많은 작업자들을 수행할때 작업들은 공유가 된다.

 

Work Queue 를 사용 해야  되는 이유

  • 쉽게 병렬 처리를 할 수 있다.
    - 작업이 밀리고 있다면 좀더 많은 worker 들을 추가 하면 된다.

  • 라운드 로빈 방식을 기본적으로 사용한다.
    -  컨슈머들은 동일한 메세지 수를 받게 된다.
    - 이렇게 균등하게 분배되는 방식을 라운드 로빈이라고 한다.

 

Message acknowledgment

  • 메세지가 정확하게 처리 되었는지 확인 할 수 있다.
    - 메세지 손실을 파악 또는 다시 큐에 넣는 작업을 할 수 있다.

작업을 처리 하는 중간에 컨슈머가 죽게 된다면 어떻게 될까?

  • 메세지 유실이 발생한다.

 

메세지가 손실 되는 과정

  • 래빗엠큐가 메세지를 컨슈머에게 전달 한다.
  • 삭제 하기 위해 메세지를 마크한다. 
  • 이러한 상태에서 작업자를 죽이면 메세지 손실이 생기게 된다. 
  • 그리고 처리되지 않은 모든 메세지가 손실이 된다.

 

어떻게 손실을 막을 수 있을까?

  • 메세지 손실을 막기 위해 레빗 엠큐는 메세지  message acknowledgments 지원한다.
  • ack 없이 컨슈머가 죽거나, 커넥션이 끊기거나, 갑자기 죽게되면 래빗엠큐는 메세지가 제대로 처리 되지 않았음을 
    인식 하게 된다.
  • 그리고 해당 메세지를 다시 큐에 넣는다.
  • 수동 메시지 확인 응답은 기본적으로 켜져 있습니다.
  • autoAck=true 플래그를 통해 명시적으로 해제했습니다.
  • 태스크가 끝나게 되면 작업자가 ack 를 보내게 해야 된다.

 

손실을 막는 방법들

Forgotten acknowledgment

  • basicAck 를 빼먹는건 일반적인 실수 지만 심각한 문제를 가져온다.
  • 예를 들어 클라이언트가 죽었을때 메세지는 재전송 되는데 
  • RabbitMQ는 압축되지 않은 메시지를 방출할 수 없기 때문에 점점 더 많은 메모리를 먹게 된다.

 

Message durability

  • RabbitMQ가 종료되거나, 죽었을때 큐와 메세지를 잊어버린다.
  • 잊어버린다는 것은 더이상 기존에 있던 것들을 찾지 못한다는 뜻인것 같다.
  • 재시작 했을때 큐가 다시 살아나기 위해서는 몇가지 설정이 필요하다.
  • 아해 처럼 durable 을 true 로 지정해주자.
boolean durable = true;
channel.queueDeclare("hello", durable, false, false, null);

* 하지만 코드 레벨에서 durable 을 true 로 지정했다고 해도 동작이 안 할 수 있다.

 - 그 이유는 이미 앞서 만들어진 큐의 durable 속성이 false 이면 반영이 안된다. 

 

Fair dispatch

  • 다음과 같은 상황일때 정상적으로 메세지 분배가 정확하게 이루어지지 않는다.
  • 두개의 워커가 있을때 홀수 번의 메세지들이 내용이 크고, 짝수 번호의 메세지들이 가볍다면
  • 무거운 작업이 하나의 워커로 몰리게 된다.

 

왜 하나의 작업자에게 무거운 작업이 몰리게 될까?

  • 이러한 현상이 발생하는 이유는 메세지가 큐에 들어오는대로 분배를 하기 때문이다.
  • n번째 메시지를 n번째 소비자에게 무작정 발송하다고 생각하면 된다.

 

그럼 어떻게 해결 할 수 있을까?

  • prefetchCount = 1 설정으로 기본 Qos 방법을 사용할 수 있다.
int prefetchCount = 1;
channel.basicQos(prefetchCount);

 

 

Note about queue size

모든 큐가 가득 찰 수 가 있는데 더 많은 작업자들을 생성하거나, 다른 전략을 써야 될 수도 있다.

 

 

 

 

 

참고 : https://www.rabbitmq.com/tutorials/tutorial-two-java.html

 

RabbitMQ tutorial - Work Queues — RabbitMQ

Work Queues (using the Java Client) Prerequisites This tutorial assumes RabbitMQ is installed and running on localhost on the standard port (5672). In case you use a different host, port or credentials, connections settings would require adjusting. Where t

www.rabbitmq.com

 

728x90
반응형

댓글