Background
대부분이 메시징 시스템이 그렇듯이, 프로듀서는 비교적 쉽습니다. 그냥 메시지를 발행하면 됩니다.
하지만 컨슈머의 경우 비즈니스의 요구사항에 따라 고려할 점이 많아집니다.
Fail over를 처리해야되는지 또는 메시지를 중복 소모를 해도 되는지 또는 병렬처리가 필요한지 또는 비동기처리를 해야되는지 등..
제가 이번에 경험한 상황은 기존에 RabbitMQ로 50개의 병렬 메시지를 동시에 처리하던 작업을 Kafka 로 마이그레이션 하는 작업입니다.
각 메시지는 처리시간이 초 단위에서 길게는 30분 까지 다양합니다.
그리고 메시지는 최대 50개를 병렬 처리해야하며, 각각의 메시지는 끝나면 큐에서 다음 메시지를 가져와서 처리해야합니다.
RabbitMQ와 Kafka는 매우 특징이 다릅니다.
RabbitMQ 는 흔히 말하는 스마트 파이프 중 하나이고 Kafka는 덤브 파이프 - 스마트 컨슈머 모델입니다.
RabbitMQ에서는 메시지 오프셋을 관리해주고 잘못 처리된 메시지에 대해 Re-queue 기능도 제공합니다.
따라서 RabbitMQ는 스마트합니다. 그만큼 컨슈머는 쉽게 구현 가능하며 코드또한 깔끔합니다.
하지만 카프카는 덤브파이프 - 스마트컨슈머 모델로, 카프카 자체에서 제공해주는 것은 그저 메시지를 보관하고 전달하는 기능입니다.
그만큼 간단하게 구현되어서 확장성과 속도면에서 우월하지만, 스마트 파이프에서 제공해주던 오프셋관리 라던가 Fail over 등 여러가지 기능들을 컨슈머를 구현할때 고려해야 합니다.
그래서 요약하자면, 이번 포스트에서는 하나의 메시지 처리가 초~30분정도 걸리고, 50개의 병렬처리가 필요한 요구사항을 카프카에서는 어떻게 처리할 수 있을지 알아보고자 합니다.
카프카에 대한 기본적인 정보는 이곳을 참조하세요.
카프카는 같은 컨슈머 그룹이라면, 파티션 1개당 컨슈머 1개만 연결될 수 있습니다.
따라서 기본적으로 파티션 개수가 병렬처리의 기준이 됩니다.
파티션이 1개라면, 하나의 컨슈머 그룹으로는 워커-스레드 모델이 아니라면 동시에 여러 메시지를 처리할 수 없습니다.
멀티컨슈머 모델을 이용해서 병렬처리를 하고 싶다면, 파티션 개수를 늘려서 컨슈머당 파티션에 대한 커넥션을 따로 가져가야 합니다.
카프카는 배치 컨슈밍이 가능하지만, 이것도 마찬가지로 파티션이 1개라면 워커-스레드 모델로 배치로 가져온 메시지를 병렬처리 하지 않는 한, 병렬처리 할 수 없습니다.
파티션을 늘리는 방법이 컨슈머 입장에서는 구현이 쉽습니다.
워커-스레드 모델을 구현하지 않아도 되고 단순히 파티션과 컨슈머만 늘려주면 됩니다.
때문에 비동기처리도 고려할 필요가 없습니다.
하나의 컨슈머는 하나의 메시지를 각 파티션에서 가져와서 처리 후 커밋합니다.
오프셋 관리도 쉽습니다. 자동으로 증가시키면 됩니다.
물론 Failover 관련해서는 추가로직이 필요해보이지만, 워커스레드에 비하면 매우 간단합니다.
그래서 파티션수를 늘리면 좋겠지만...병렬처리만을 위해 카프카의 파티션을 늘리는 것에는 한계가 있습니다.
오버헤드가 커진다고 판단해서 카프카담당 팀에서 파티션 수에 제한을 둡니다.
그리고 파티션은 증가만 가능하고 수축이 불가능합니다. 따라서 병렬처리 개수 N 개가 확장성이 좋지 못합니다.
지금까지 정리하자면
- 50개의 메시지를 병렬처리해야 되는 상황으로 가정합니다. 각 메시지는 1초~30분 처리시간을 갖습니다.
- 병렬처리를 위한 방법으로는 크게 두 가지 방법이 있습니다.
1) 워커스레드를 늘리는 방법 - 아래 모델에선 Single Consumer(워커-스레드) 모델에 해당
2) 파티션&컨슈머 수를 늘리는 방법 - 아래 모델에선 Multi Consumer 모델에 해당
- 멀티 컨슈머 모델은 컨슈머 스레드를 이용해서 비즈니스 로직을 처리하므로 아무래도 별도의 스레드를 생성하는 워커-스레드 모델보다 구현이 쉽습니다.
- 스케일-아웃이 자주 발생하면, 워커스레드 모델을 사용할 것을 권장하고, 그렇지 않고 파티션 수에 확장이 없다면 컨슈머 스레드를 사용하는 것도 괜찮습니다.
- 그룹1의 컨슈머들은 메시지 1~25를 가져온다.
- 그룹1의 컨슈머들은 워커에게 작업을 할당한다.
- 그룹1의 컨슈머들은 작업상태를 DB에 업데이트한다.
- 그룹2의 컨슈머들은 메시지 1~25를 가져온다.
- 그룹2의 컨슈머들은 DB 상태를 확인하여 메시지 1~25가 그룹1에 의해 처리되었음을 확인하고 워커에게 작업을 할당하지 않고 커밋처리한다.
- 그룹2의 컨슈머들은 다음 poll을 통해 26~50 메시지를 가져와서 처리한다.
'개발 > Messaging system' 카테고리의 다른 글
SQS with Spring (0) | 2018.10.31 |
---|