Programming/Development

[ Message Broker ] Kafka, RabbitMQ, Redis(Pub/Sub)

Ho-home 2024. 9. 5. 17:38

서론


Chatting Server를 구현할 일이 생겼습니다.

 

기본적으로, Chatting은 서버와 클라이언트 간 세션 수립을 기반으로 작동하며, 양방향 통신에 의해 로직이 이루어지는 Websocket프로토콜을 사용합니다.

(Websocekt프로토콜이 나오고, HTTP API를 사용한 Polling은 사실상 실시간 채팅에 사용하는 서비스가 있을지 의문인데,  생각보다 채팅 구현관련 레퍼런스를 찾아보면 Polling과 관련한 내용도 자주 볼 수 있었네요.. why..? 굳이..?)

 

 

Chatting Server를 구현하려면 높은 리소스를 잡아먹는 도메인 특성상, 또한 서버와 Connection이 가능한 클라이언트 수가 제한이 되기 때문에 서비스의 규모가 증가함에 따라 'Scale-out'은 필수적이기 때문에, 늘 염두에 둬야한다고 생각했습니다.

하지만, Websocket 프로토콜을 사용하는 채팅서비스 특성 상, 서버가 scale-out이 되면 세션이 분산이 됩니다.

 

예를 들어봅시다.

A서버 ,B서버, C서버에는 채팅서비스가 동일하게 구현이 되어있습니다.

 

초창기 서버에는 클라이언트 수도 많지 않고, CPU 사용률이 서버를 유지하는 데에 큰 문제점이 되지 않습니다.

이에따라 A서버만으로 충분한 퍼포먼스를 내줄 수 있었습니다.

하지만, 클라이언트가 점차 늘어나고, 서비스의 규모도 늘어남에 따라 실시간 채팅서비스로 인해 CPU사용량이 점차 늘어나, 서버의 성능에 영향을 미치게되었으며, 설상가상으로 클라이언트 수가 늘어나 하나의 서버만으로는 Connection을 감당하기 어려워졌습니다.(AWS EC2 instance의 m2.4xlarge기준, 50만개의 소켓 수립이 일어나면 CPU사용량의 60%정도가 할당됩니다.

[refhttps://stackoverflow.com/questions/17448061/how-many-system-resources-will-be-held-for-keeping-1-000-000-websocket-open/17453704#17453704\

 

이 문제를 해결하기위해 A서버에만 소켓 연결(세션 수립)을 하던 서비스를 추가적인 서버를 사용하여 B서버, C서버를 사용하고, 세션을 배분하는 로직을 작성하여 다시 서비스를 가동시킵니다.

허나, A서버에 세션이 연결되어있던 클라이언트의 메시지가 B서버에 연결 된 다른 클라이언트에게 전달이 되지않음을 확인하였습니다.

이 문제를 어떻게 하면 해결할 수 있을까요?

 

 

이를 위한 기술이 바로 Message Broker입니다.

 

 

MessageBroker?


Message Broker (Ref by. Wikipedia)

 

메시지 브로커는 발신자(Publisher)의 공식 메시징 프로토콜에서 수신자(Subscriber)의 메시징 프로토콜로 메시지를 변환하는 중개 모듈입니다.

메시지 브로커의 가장 중요한 점은, 브로커가 수신자가 온라인 상태거나, 혹은 오프라인 상태이더라도 메시지를 수신할 수 있도록 한다는 점입니다. 즉, 메시지 송신의 대상이 되는 서버가 죽는다고 하더라도 메시지를 수신할 수 있도록 만듭니다.

(Message Broker는 수신자가 메시지를 수신 하였는지를 확인할 수 있습니다.)

 

메시지 브로커는 메시지 큐(Message Queue)를 사용하며, 메모리나 하드 디스크에 메시지를 저장합니다. 

메시지 큐는 메시지를 받은 순서대로 저장하고, 같은 순서로 수신자들에게 보내는데 어떠한 이유로 메시지를 전달할 수 없는 경우에 (주로 네트워크 문제) 메시지는 대기열의 나중으로 일정을 변경하며, 수신이 확인될 때 까지 대기열에 남아있습니다.

 

 

만약, 마이크로서비스 아키텍처 (MSA)를 사용하여 시스템을 구축하는 경우에, 서로 간 통신이 문제가될 수 있는데 Message Broker를 중앙 브로커로 사용하면 마이크로서비스가 서로 통신할 수 있습니다.

또한 다른 서비스를 추가해야할 경우에 메시지 브로커와 연결하기만 하면 됩니다.

여기서, MSA는 API의형식으로 서로 다른 서비스 간 통신하는 아키텍처 구조인데, 왜 Message Broker를 사용하는지에 대해 의아하신 분들이 계실거라 생각합니다.

 

일반적으로 MSA는 두 가지 방법으로 서로 통신하는데, 동기 통신과 비동기식 통신입니다.

동기식 통신에서는 여러분이 알고계시듯, 호출자가 다음 메시지를 보내기 전 응답을 기다리는 형태로 통신을 하며 HTTP 메소드를 사용한 REST API를 토대로 통신합니다.

허나, 두 번째 방법인 비동기방식으로 통신을 하기위해서 응답을 기다리지않고 메시지를 Message Broekr에 전송하기만 하면 Message Broker측에서 해당 동작을 서버 입장에서 비동기의 형태로 처리를 해주기때문에 Message Broker를 사용한다고 할 수 있습니다.

 

예를들어, Rest API를 통해 클라이언트와 서버 간 통신이 이루어지는 상황이라고 가정해봅시다.

Client - Server구조를 가진 아키텍처의 경우에는 HTTP Protocol을 사용하는데, 만약 요청에 대한 응답 데이터가 장시간 처리 (예를 들자면 10분)이 걸린다고 하면 클라이언트와의 연결이 종료가 될 경우 작업이 초기화되어버리고, 이 데이터를 요청하기 위해서 클라이언트는 다시 처음부터 요청을 할 경우가 생겨버립니다.

이러한 경우에 Message Broker를 통해 메시지 전달을 보장할 수 있습니다. (클라이언트가 요청을 보내면, 서버측에서 처리를 하고, Message Broker를통해 클라이언트에 데이터를 넘겨주면 됩니다. 위에서 언급했 듯, Message Broker는 수신자가 데이터를 받았는지를 확인할 수 있습니다.)

 

 

메세지 브로커 모델에는 여러 모델이 있으나, 주요 두 가지 메시징 패턴에 대해 알아봅시다.

 

1. Point To Point

Point To Point Model

 

- 메시지 큐는 메시지 발신자(Publisher) 와 수신자(Subscriber)간 일대일 관계를 갖습니다. 대기열의 각 메시지는 한 명의 수신자에게 전송되고, 한 번만 수신됩니다.

- 이 경우에는 주로 한 번의 수행에 포커싱이 된 경우이므로, 금융 거래 처리에 최적화 되어있습니다.

 

2. Publish-Subscribe

Pub/Sub Model

- 이 모델에서 메시지 큐는 메시지 발신자와 수신자 간 일대다(One To Many) 관계를 갖습니다.

이 모델에서는, 발신자가 한 주제에 대한 메시지를 게시하면 해당 주제를 구독(Subscribe)한 모든 소비자에게 배포가 됩니다.

- 이 모델은 여러 관계자 간 데이터를 지속적으로 공유해야 하는 시스템에 사용할 수 있습니다.

 

 

 

Message Broker의 장점

  • 메시지 전달 보장 : 소비자(서버)가 온라인(Running) 상태가 아니더라도 활성화가 되면 메시지가 전달이 됩니다.
  • 비동기 처리로 인한 시스템 성능 향상 : 시간이 오래 걸리는 프로세스는 별도로 처리할 수 있으므로 애플리케이션의 메인 스레드에 영향을 주지 않습니다.
  • 애플리케이션이 서로 다른 프로그래밍 언어로 구현되어있다 하더라도 통신할 수 있습니다.

 

Message Broker의 단점

이렇게 완벽할것만 같은 Message Broker에도 단점은 존재합니다.

  • 러닝 커브 : 여러가지 메시지 브로커와 이를 사용할 수 있는 디자인 패턴이 있습니다. 여러 메시지 브로커 간 차이점과, 어떤것을 어떻게 사용해야 하는지, 메시지 브로커를 설정하는 구성 프로세스 등을 학습하는 데에 비용이 생깁니다.
  • 디버깅 : 시스템이 복잡해지면 디버깅이 어려워질 수 있습니다.
  • 복잡성 : 메시지 브로커가 있으면 시스템 아키텍처에 완전히 새로운 구성요소가 추가되므로, 도입 시에 복잡성이 증가합니다.

 

 

Message Broker의 종류

메시지 브로커를 선택할 때에는 몇 가지 사항을 고려하여야합니다.

- 브로커 규모 : 시스템에서 초당 전송되는 메시지 수

- 데이터 지속성 : 메시지 복구 기능

- 소비자 기능 : 브로커가 일대일(Point To Point) 또는 일대다(One To Many) 관리가 가능한지에 대한 여부

  1. Apache Kafka : 2011년에 링크드인에서 만든 Message Broker로, 웹 및 Desktop 애플리케이션, 마이크로서비스, 모니터링 및 분석 시스템, NoSQL, 오라클, 하둡과 같은 다양한 시스템에서 작동할 수 있어 인기있는 소프트웨어입니다.
  2. Rabbit MQ : Rabbit Technologies Ltd에서 개발한 Message Broker로, 클라우드 환경, 온프레미스 및 로컬 컴퓨터에 쉽게 배포할 수 있습니다.
  3. Redis (pub/sub) : 이벤트 발생 시 게시자가 모든 구독자에게 메시지를 배포하는 푸시 기반 시스템을 제공합니다. 인메모리 구조를 띈다는 점이 있습니다.

 

 

RabbitMQ (AMQP)


RabbitMQ는 2007년에 출시된 최초의 일반 메시지 브로커 중 하나입니다.

고급 메시지 큐 프로토콜(Advanced Message Queuing protocols - AMQP)을 구현하여 pub/sub 방식을 통해 메시지를 전달하는 오픈 소스이며, 복잡한 라우팅 로직을 지원하도록 설계되었습니다.

 

RabbitMQ Message Broker

 

RabbitMQ에서 사용된 메시지는 삭제되기 때문에 RabbitMQ를 사용하여 로그를 집계하기는 어렵습니다.

사용된 메시지를 저장하기 위해서는 생산자가 저장한 메시지를 스트림하여야합니다.

RabbitMQ는 푸시 모델을 적용하므로, 생산자는 클라이언트 애플리케이션이 메시지를 사용하였는지 여부에 대해 알 수 있습니다.

따라서, 데이터를 교환하고 분석할 때 특정 순서 및 전달 보장을 준수하여야 하는 애플리케이션에 적합합니다.

 

  • 성능 : 구성과 리소스에 따라 초당 50,000 메시지 정도를 처리할 수 있습니다.
  • 지속성 : 영구(Persistence) 메시지, 일시적(Temporary) 메시지 모두 지원합니다.
  • Point To Point / One To Many를 지원합니다.

RabbitMQ의 생산자는 메시지를 보내고, 메시지가 의도한 소비자에게 도착하는지 모니터링합니다.

예를들자면, 우편물을 받아서 수취인에게 배달하는 우체국이라고 생각하면 됩니다.

 

 

메시지 사용

브로커는 소비자가 메시지를 수신하게하며, 소비자 애플리케이션은 수동적 역할을 하여 브로커가 메시지를 대기열로 푸시할 때까지 기다립니다.

 

메시지 우선순위

또한, RabbitMQ는 우선순위 대기열을 사용하여 특정메시지를 에스컬레이션할 수 있다는 장점이 있는데, 선입선출(FIFO)순서로 메시지를 보내는 대신에 우선순위가 높은 메시지를 일반 메시지보다 먼저 처리할 수 있습니다.

 

메시지 정렬

RabbitMQ는 메시지를 특정 순서로 보내고, 대기열에 추가합니다. 우선 순위가 더 높은 메시지가 시스템 대기열에 추가되지 않는 한 소비자는 전송된 순서대로 메시지를 받습니다.

 

메시지 삭제

RabbitMQ 브로커는 메시지를 대상 대기열로 라우팅합니다. 소비자는 메시지를 읽으면 브로커에 확인(ACK - 응답패킷) 응답을 보내고, 브로커는 ACK를 확인하여 해당 메시지를 삭제합니다.

 

 

Kafka


분산 스트리밍 플랫폼인 Kafka는 2011년 Linkdin에서 높은처리량과 짧은 지연시간 처리를 위해 만든 서비스로, pub/sub 방식을 제공합니다.

데이터의 지속성을 제공하고, 레코드 스트림을 저장하여 고품질 메시지로 교환할 수 있도록 해줍니다.

 

Kafka Message Broker

대량의 데이터를 장기간 저장하기 위해 구축된 처리량이 높은 분산형 아키텍처에 유용하며, 수신된 데이터를 여러 번 처리할 수도 있기떄문에 수신된 데이터를 다시 분석해야 하는 애플리케이션에 적합합니다.

또한, 메시지를 스트리밍할 때 지연시간이 매우 짧기때문에 스트리밍 데이터를 실시간으로 분석하는 데 적합합니다.

 

  • 성능 : 초당 최대 수백만개의 메시지를 전송할 수 있습니다.
  • 지속성 : 제공합니다.
  • One To Many만 지원합니다.

 

Kafka의 메시지 생산자는 소비자가 메시지를 검색했는지 여부에 관계없이 메시지를 대기열에 게시합니다.

예를들어, 생산자가 다양한 장르의 메시지를 진열대에 정리하는 상황과 비슷합니다.

소비자는 각 진열대에 진열된 메시지를 읽고, 읽은 내용을 기억합니다.

 

 

메시지 사용

메세지가 물리적 로그 파일에 추가가 되면 소비자는 마지막으로 읽은 메시지를 추적(offset 추적)하고, 그에 맞게 오프셋 트래커(메시지를 읽은 후 증가하는 Counter)를 업데이트합니다.

Kafka를 사용하면 생산자는 소비자가 메시지를 검색 하는것을 인지하지 못합니다.

 

메시지 우선순위

RabbitMQ와는 다르게, 우선순위 대기열을 지원하지 않으며, 메시지를 해당 파티션에 분산할 때 모든 메시지를 동등하게 취급합니다.

 

메시지 정렬

토픽과 파티션을 사용하여 메시지를 대기열에 추가합니다.

생산자가 메시지를 보내면 해당 메시지는 특정 토픽과 파티션으로 들어갑니다.

생산자-소비자 직접 교환을 지원하지 않기 때문에 소비자는 파티션에서 메시지를 끌어옵니다.

 

메시지 삭제

RabbitMQ와는 다르게 메시지를 로그파일에 추가하며, 메시지는 보존 기간이 만료될 때까지 보관됩니다.

따라서 소비자는 보존기간 내에 언제든이 스트리밍 된 데이터를 다시 처리할 수 있습니다.

 

 

Redis


Redis는 고성능 Key-Value 저장소 또는 메시지 브로커로 사용할 수 있는 인메모리 데이터 저장소라는 것이 핵심입니다.

이 메시지 브로커는 지속성이 없으며, 메모리와 DB에 덤프한다는 점이 있으며, 인메모리 데이터 저장소에 걸맞게 실시간 데이터 처리에 적합합니다.

  • 성능 : 초당 최대 백만개의 메시지를 전송할 수 있습니다.
  • 지속성 : 기본적으로 인메모리 데이터 저장소이므로, 일시적 메시지만 지원합니다.
  • Point To Point / One To Many를 지원합니다.

주로, 지속성이 그리 중요하지 않고 약간의 손실을 감당할 수 있는 짧은 보존기간의 메시지에 유용합니다.

 

 

 

그래서 이 Message Broker를 사용하면 채팅 서비스에 어떤 영향을 주느냐?


Message Broker를 사용하면, 기존 서버증설로 인해 서로 다른 세션 간 소통이 이루어지지않던 채팅서비스의 경우, 클라이언트로부터 메시지를 받은 서버측에서 Message Broker에 해당 데이터를 송신합니다.

이후, Message Broker는 데이터에 대한 전처리과정을 거쳐 Subscriber들에게 이 데이터를 broadcasting하게되는데, 이 과정을 거쳐 다른 서버의 서로 다른 세션들에게도 메시지를 공유할 수 있게됩니다. 

 

저의경우 Message Broker를 선택한 기준은 아래와 같습니다.

1. Redis는 인메모리위주의 broker이다보니 채팅서버가 증설될 경우 runTime동안 받지못한 데이터를 동기적으로 접근할 수 있게끔 처리할 수 없을것.

2. kafka의 경우 현재 서비스의 특성 상 높은 트래픽이 기대 되는사항은 아니며, 채팅데이터의 보관성이 중요한 서비스가 아니기에 로그형태로 저장할 필요까지는 없다고 판단

3. 높은 성능의 인스턴스도 가용할 수 없기에, kafka 전용 로그데이터를 추가적으로 모아둔다는 것 자체가 인프라적 리소스낭비라고 판단.

 

따라서, 현재로서는 낮은 처리량과 짧은 지연시간에 특화된 작고 귀여운 RabbitMQ를 사용하는것이 최선이라고 생각이 들어 RabbitMQ를 채택하였습니다.

 

 

 

 

출처

https://kakaoentertainment-tech.tistory.com/109

 

라이브채팅 플랫폼 구현기 1탄 : 개발 언어 및 기반기술 조사

2022년 초, 멜론뮤직어워드(MMA) 2022 행사를 준비하는 과정에서 기존 MMA 생중계 시 사용되는 댓글 시스템이 사용자 참여에 불편함이 있었고, 이를 해소하기 위해 '실시간 채팅 플랫폼'의 필요성이

kakaoentertainment-tech.tistory.com

https://hasithas.medium.com/introduction-to-message-brokers-c4177d2a9fe3

 

Introduction to Message Brokers

What is a message broker?

hasithas.medium.com

https://dev.to/assyahid/redis-kafka-or-rabbitmq-which-microservices-message-broker-to-choose-55k8

 

Redis, Kafka or RabbitMQ: Which MicroServices Message Broker To Choose?

When using asynchronous communication for Microservices, it is common to use a message broker. A brok...

dev.to

https://aws.amazon.com/ko/compare/the-difference-between-rabbitmq-and-kafka/

 

RabbitMQ와 Kafka - 메시지 대기열 시스템 간의 차이점 - AWS

RabbitMQ는 간단한 아키텍처로 복잡한 메시지 라우팅을 제공하는 반면, Kafka는 애플리케이션이 스트림 기록의 데이터를 처리할 수 있을 만큼 내구성이 우수한 메시지 브로커 시스템을 제공합니다.

aws.amazon.com