참고

https://www.ibm.com/kr-ko/cloud/learn/message-brokers

 

Message Broker(메시지 브로커)는 Publisher(송신자)로부터 전달받은 메시지를 Subscriber(수신자)로 전달해주는 중간 역할이며 응용 소프트웨어 간에 메시지를 교환할 수 있게 한다.

애플리케이션 To 애플리케이션으로 직접 메세지를 송수신 하는 방식과 비교해, 애플리케이션 간의 결합을 낮추고 확장에 보다 더 유연하게 대처할 수 있다는 장점이 있다.

메세지 브로커는 메세지를 전달하는 방식에 따라서 크게 2가지 종류가 있다.

 

포인트-투-포인트 메시징

메시지의 송신자와 수신자 간에 일대일 관계를 지닌 메시지 대기열에서 사용되는 분배 패턴입니다. 큐의 각 메시지는 하나의 수신자에게만 전송되며, 오직 한 번만 이용됩니다. 포인트-투-포인트 메시징은 메시지가 한 번만 실행되어야 하는 경우에 호출됩니다.

쉽게 말해서, 브로커가 직접 클라이언트로 메세지를 보내주는 방식으로 push 방식에 해당한다. 대표적으로 RabbitMQ(pull 방식을 지원하는 API 가 있지만 성능이 좋지 않다.) 가 있다.

 

발행/구독 메시징

이 메시지 분배 패턴(종종 "발행/구독"이라고 함)에서 각 메시지의 생성자는 이를 토픽에 발행하고, 다수의 메시지 이용자는 해당 메시지를 수신하고자 하는 토픽을 구독합니다. 토픽에 대해 발행된 모든 메시지는 이를 구독한 모든 애플리케이션에 분배됩니다. 이는 메시지의 발행자와 이용자 사이에 일대다 관계가 있는 브로드캐스트 스타일의 분배 방법입니다.

쉽게 말해서, 브로커에 데이터가 있고 이를 클라이언트가 요청해서 받아가는 방식으로 pull 방식에 해당한다. 대표적으로 Kafka 가 이에 해당한다.

지속적인 요청을 보내서 결과를 기다리는 방법을 polling 이라고 하는데, 발행/구독 메시징 브로커의 경우 일부 polling 방식을 기반으로 메세지를 받아와 처리한다.

 

 

polling 방식의 경우 서버에 주는 부담이 크다. 그래서 대안으로 long polling 방식을 많이 사용한다. Redis 를 예시로 long polling 을 설명해본다. long polling 방식은 서버측이 클라이언트의 연결을 물고 있다가, 서버 측에 락 획득 가능 이벤트가 일어나면 클라이언트 측에 알림을 보내고 이후 클라이언트가 락 획득을 시도한다.

즉, 바로 응답을 하는 것이 아니라 연결만 물고 있다가 응답 가능 상태가 되면 클라이언트에 알림 응답을 보내주고 이때 클라이언트가 재 요청을 하는 것이다.

 

 

kafka 가 공식적으로 내놓은 Java 클라이언트 라이브러리인 apache kafka-clients 의 경우 long polling 방식을 사용하고 있다. 여기서 KafkaConsumer.poll(long) 메소드를 사용한다.

그런데 이는, 서버 측에서 이벤트가 일어나지 않을 경우 연결을 계속 물고 있기 때문에 poll 메소드가 무한정 대기하는 상태가 발생할 수 있다. 따라서 kafka 2 점대 버전 부터는 응답이 없어 timeout 이 날 경우, 빈 collection 을 반환하는 KafkaConsumer.poll(Duration) 메소드 사용을 권장하고 있다.

 

 

각각 방식에 따라서 특징이 있는데 다음과 같습니다.

 

push 방식

이 접근 방식은 브로커가 클라이언트에게 메세지를 보내줍니다. 따라서 데이터가 클라이언트에 의해 처리되는지 확인하는 의무는 클라이언트가 아닌 브로커에 있습니다. 또한 클라이언트는 브로커만 제어하고 모니터링하기 때문에 브로커로부터 이벤트 수신 지연이나 지연에 대해 걱정할 필요가 없습니다.

따라서 클라이언트 앱이 다운되면 브로커가 지속적으로 데이터 푸시를 시도 해야하는 상황이 됩니다.

이런 상황 속에서 여러 클라이언트가 메세지를 요청한다고 가정하면, 브로커는 각 클라이언트에게 데이터를 푸시하는 것이 큰 부담이 됩니다.

 

pull 방식

클라이언트는 브로커에게 요청했던 마지막 메세지에 대한 내용을 브로커의 로그에 기록합니다. 그래서, 다음에 메세지를 요청 할 때는 해당 기록을 보고 이미 받은 메세지 이후의 것만 브로커에 요청할 것입니다.

이런 방식 때문에 브로커에겐 정보가 잘 처리 되었는지 확인할 의무가 없습니다. 클라이언트 앱이 다운되어 메세지 처리가 뒤쳐질 수 있는데, 이런 경우 브로커는 클라이언트 이러한 문제에 대해 걱정할 필요가 없습니다.

풀 기반의 유일한 문제는 브로커에 더 이상 데이터가 없고 클라이언트가 새 이벤트를 기다리거나 요청하려고 할 때 지속적인 polling 요청이 브로커에 들어오면서 불필요한 트래픽을 유발한다는 점입니다.

이 문제를 극복하기 위해 브로커에 이벤트가 생길 때까지 (보내줄 메세지가 생길 때까지) 대기 하는 long polling 방식을 이용하기도 합니다.