3줄 선요약
- AWS 에는 스팟 인스턴스(Spot Instance)는 인스턴스가 죽을 수 있다.
- 처리 도중 리밸런싱이 발생하면 오프셋 커밋을 하지 않아서 중복으로 메시지를 처리할 수 있다.
- 컨슈머는 at least once 라는 것을 고려해서 개발해야한다.
컨슈머 리밸런싱이란?
카프카의 컨슈머 그룹내의 특정 컨슈머가 동작하지 않으면, 파티션을 다른 컨슈머에게 재할당하게 되는데, 이를 리밸런싱이라고 한다.
리밸런싱은 크게 아래의 과정을 거치게 된다.
- 트리거: 컨슈머 그룹에 변경 발생시 리밸런싱이 트리거 된다.
- 파티션 재할당: 브로커는 그룹 코디네이터 역할을 하는데, 현재 컨슈머 그룹에 대해 파티션을 재할당한다.
- 리밸런싱 진행
- 프로세스 재게
컨슈머를 추가하거나, 컨슈머가 장애가 나서 중단되는 경우에 리밸런싱이 일어나게 된다.
일반적으로는 컨슈머를 블루그린 배포시, 기존의 컨슈머가 제거되면서 리밸런싱을 하게 된다.
리밸런싱의 필요성
애플리케이션 운영시 가용성은 중요한 요소이다. 만약에 컨슈머 하나가 중단되었는데, 리밸런싱이 없으면 어떻게 될까?
아래 그림에서 두번째 컨슈머가 죽은 경우, 특정 파티션 내의 이벤트가 처리가 안되는 일이 발생한다. 브로커가 이를 인지하고 처리하지 않는다면, 특정 파티션의 메시지들은 컨슈머가 복구될 때까지 기다려야 한다.
브로커는 컨슈머 그룹에 변화가 생기는 경우, 리밸런싱을 통해서 파티션이 다른 컨슈머에 할당될 수 있도록 하여 가용성 이슈를 해결한다.
컨슈머는 at least once…
카프카는 별다른 설정을 하지 않는 경우, default 값으로 at least once delivery 전략을 채택한다.
즉, 컨슈머가 메시지를 읽은 후 커밋하지 않은 경우에 해당 메시지를 다시 수신하게 된다.
사내 개발망에서 테스트를 하는데, 컨슈머가 락이 걸려서 제대로 수행이 되지 않는 문제가 있었다.
문제를 해결하기 위해 로그를 보니, 같은 메시지를 컨슈머가 두 번 이상 수신하고 있던 것이 문제였다.
같은 유저가 짧은 시간내에 같은 기간에 대한 요청을 두번하는 경우를 대비하여 내부적으로 redis lock 을 걸어두었는데, 메시지 처리가 끝나지 않은 상태에서 다시 요청이 와서 락에 걸린 것이었다. 문제는 최초 요청에 대한 처리가 완료되었다는 로그가 없었다.
그래서 로그를 좀 더 살펴보니, 컨슈머가 리밸런싱 된 로그가 있었다.
이 문제의 원인은 개발망에서는 스팟 인스턴스를 사용한다는 거였는데, AWS 스팟 인스턴스의 경우 온디맨드에 비해 가격이 저렴하지만, 애플리케이션이 중간에 중단될 가능성이 있다는 것이었다.
즉, 정리하자면 아래와 같았다.
- 스팟 인스턴스로 인해 서버가 죽음
- 따라서, 기존 컨슈머는 락을 release 하지 않고, 메시지 커밋을 하지 못한채 죽음.
- 컨슈머 재시동시 같은 메시지를 다시 읽음.
- 해당 메시지에 대해 락이 걸려있어서 실패.
일반적으로, spring framework 나 nestjs 와 같은 컨테이너 프레임워크들은 애플리케이션이 중단되는 시그널을 받으면, 특정 로직을 수행할 수 있는 훅이 있다. 컨슈머는 언제든 같은 메시지를 여러번 수신할 수도 있다. 그렇기 때문에 lock 을 걸 때는 이러한 점을 고려해서, release 하는 로직을 작성해야한다.
'카프카' 카테고리의 다른 글
카프카 톺아보기 3-1. 컨슈머 개념 (1) | 2024.05.30 |
---|---|
카프카 톺아보기2 - CLI (0) | 2024.05.30 |
카프카 - 메시지 유실 가능성 (0) | 2024.05.23 |
카프카 톺아보기 - 기본개념 (0) | 2024.02.25 |