카프카 클라이언트가 파티션을 찾는 방법
카프카 클라이언트와 토픽-파티션
카프카가 메세지를 토픽-파티션 단위로 복제하여 관리하는 것은 이미 알고 있는 사실이다. 카프카 클러스터의 브로커들 중 어떤 브로커도 한 토픽의 모든 데이터를 가지고 있지는 않은 것이다. 이런 시스템에서는 자연스럽게 몇 가지 의문이 생긴다. 파티션은 어떻게 관리되는 것일까? 프로듀서가 발행한 메세지는 어느 파티션에 저장되고 컨슈머는 어떻게 원하는 파티션에서 메세지를 읽어올 수 있을까?
특정 토픽의 메세지에 대한 읽기/쓰기 요청을 어느 파티션에서 처리할지는 카프카 클라이언트가 직접 제어하며, 브로커가 자체적으로 결정하는 체계는 없다. 즉, 프로듀서는 토픽에 메세지를 발행할 어느 파티션에 쓸지 직접 지정해야 하며 마찬가지로 컨슈머도 메세지를 읽을 토픽의 파티션을 직접 지정해야한다. 두 개의 클라이언트가 같은 파티셔닝 스킴을 사용하려면 반드시 같은 키-파티션 매핑 메소드 계산 방식을 사용해야 한다.
이 과정에서 메세지를 읽고 쓰는 요청은 그 파티션의 리더에게만 할 수 있는데, 이 제약 조건은 브로커에서 검증하기 때문에 리더가 아닌 브로커에게 요청하는 경우 NotLeaderForPartition
오류가 발생한다. (파티션 복제 구조에서 브로커는 리더-팔로워로 나눠진다. 팔로워는 리더에 쓰여진 메세지를 복제하여 저장한다.)
그렇다면 클라이언트는 어떻게 현재 어떤 토픽이 존재하는지, 몇 개의 파티션이 있는지 그리고 어떤 브로커가 각 파티션들의 리더인지 알고 올바른 호스트에게 요청을 보낼 수 있을까? 이 정보는 유동적이라 각 클라이언트에 정적 매핑 파일 등으로 설정할 수 없다. 대신 모든 카프카 브로커가 클라이언트의 클러스터 메타데이터(어떤 토픽이 존재하는지, 몇 개의 파티션이 있는지 그리고 어떤 브로커가 그 파티션의 리더인지, 각 브로커의 호스트와 포트 정보) 요청에 응답할 수 있도록 되어있다.
다시 말해, 클라이언트는 *어떻게든 하나의 브로커를 찾아 그 브로커에게 다른 모든 브로커들과 그 브로커들이 호스팅하는 파티션 정보를 요청한다. 이 최초의 브로커가 다운될 수도 있으므로 클라이언트는 부트스트래핑을 위해 두 세개 이상의 브로커 URL을 알고 있어야 한다. 로드밸런서를 지정하거나 두 세개의 카프카 호스트를 정적으로 설정하는 방식을 사용할 수 있다.
클라이언트는 폴링을 이용해 계속해서 변화를 알아낼 필요는 없다. 메타데이터가 만료되었다는 오류가 발생하기 전까지는 클라이언트가 처음 구동될 때 가져온 메타데이터를 캐싱한다. 이 에러는 두 개의 형태로 발생하는데, 클라이언트가 특정 브로커와 통신에 실패했을 때, 혹은 데이터를 요청한 브로커가 더 이상 그 파티션의 리더(호스트)가 아닌 경우이다.
정리하자면,
- 클라이언트는 부트스트랩 리스트(bootstrap.url)에 있는 카프카 브로커 URL을 순회하며 연결 가능한 하나의 브로커를 찾고 클러스터 메타데이터를 가져온다.
- 메타데이터를 기반으로 토픽-파티션의 호스트인 적절한 브로커에 메세지를 읽고 쓴다.
- 메타데이터 에러가 발생하면 메타데이터를 새로고침하고 재시도한다.