메시지 브로커(Message Broker)는 프로그램(서비스) 간 비동기를 위해 메시지 형태로 통신하는 소프트웨어입니다. 여기서는 메시지를 발행하는 주체를 Producer, 메시지를 소비하는(받는) 주체를 Consumer라고 하겠습니다.
메시지 큐(Message Queue)는 프로그램 간 비동기 통신을 위해 사용되는 방법입니다. 메시지 브로커에서 발행한 메시지를 저장한 수단이 필요한데 이를 메시지 큐라고 합니다.
메시지 브로커는 어떨 때 사용할까요?
MSA 아키텍처로 구성되있는 주문 서비스와 배송 서비스가 있다고 가정해보겠습니다. 주문 서비스에서 주문이 완료되면 배송 서비스에 배송 시작 요청을 보냅니다. HTTP API를 사용해서 주문 서비스 -> 배송 서비스로 요청을 보냈을 때 배송 서비스가 다운되있다면 어떻게 될까요? 해당 요청은 배송 서비스가 받지 못해 누락됩니다.
이런 경우를 방지하기 위해 메시지 브로커를 사용합니다. 메시지 브로커로 메시지를 발행하고 이를 메시지 큐에 저장합니다. 배송 서비스가 정상이라면 큐에 있는 메시지를 소비하여 정상적으로 처리하고, 다운돼있다면 큐에 메시지를 보관하고 있다가 정상으로 돌아왔을 때 메시지를 소비하여 처리합니다.
메시지 큐에 있는 메시지를 소비하는 방법은 두가지가 있습니다. 브로커가 Cosnumer에 메시지를 보내는 Push 모델, Consumer가 브로커에 있는 메시지를 가져오는 Pull 모델입니다. Push 모델은 RabbitMQ에서, Pull 모델은 Kafka에서 사용되는 방법입니다.
메시지 큐는 이름 그대로 큐(Queue)이기 때문에 FIFO 성질을 가지고 있습니다. 따라서 Producer가 발행한 메시지 순서대로 Consumer에서 소비할 수 있습니다.
Kafka에서는 여러개의 파티션을 만들 수 있습니다. 각 파티션을 큐라고 생각하면 됩니다. 하나의 파티션 안에서는 순서가 보장되지만 여러 파티션에 걸쳐서는 순서가 보장되지 않습니다. 주문 성공 메시지가 발행되고 이어서 주문 취소 메시지가 발행됐다고 가정해보겠습니다. 순서가 보장되지 않는다면 주문 성공이 되기도 전에 취소가 먼저 처리되는 일이 발생합니다. 특정 Key를 기준으로 파티션을 나눠 순서를 보장할 수 있습니다. 예를 들어 주문 성공 시 생긴 주문 ID를 Key로 가진 파티션에 발행하고 마찬가지로 주문 취소도 주문 성공에서 나온 주문 ID를 Key로 가진 파티션에 넣으면 파티션 안에서는 순서가 보장되게 됩니다.