카프카는 거의 모든 구성을 튜닝할 수 있지만 특별한 경우가 아니면 바꿀 일이 없는 옵션이 대부분이다. 단일 서버로 혼자 돌린다면 기본값으로 써도 되고, 클러스터로 묶는 순간 반드시 봐야 하는 것들이 생긴다.
클러스터로 묶을 때 보는 설정
클러스터로 묶을 때 보는 것부터 본다.
broker.id는 클러스터 안에서 전부 달라야 한다. 호스트별로 고정된 값을 쓰는 것이 강력히 권장된다. host1.example.com이면 1, host2.example.com이면 2처럼 잡는다.
listeners는 {프로토콜}://{호스트}:{포트} 형태다. 호스트가 0.0.0.0이면 모든 네트워크 인터페이스에서, 비어 있으면 기본 인터페이스에서만 연결을 받는다. 1024 미만 포트는 루트 권한으로 카프카를 실행해야 하므로 권장하지 않는다.
zookeeper.connect는 {호스트}:{포트}/{경로} 형태이고, 마지막 경로가 chroot다. 자세한 것은 주키퍼 쪽에 있다.
log.dirs는 로그 세그먼트를 저장할 디렉토리 목록이다. 여기에 놓치기 쉬운 동작이 있다. 새 파티션의 저장 위치를 디스크 사용량이 아니라 이미 저장된 파티션 수를 기준으로 정한다. 파티션 크기가 제각각이면 디렉토리별 데이터 양이 균등해지지 않는다는 뜻이다. 같은 파티션에 속하는 로그 세그먼트는 동일 경로에 모인다.
num.recovery.threads.per.data.dir는 로그 세그먼트를 관리하는 스레드 풀의 크기다. 브로커가 정상 시작할 때 각 파티션의 세그먼트 파일을 열고, 장애 후 재시작할 때 검사해서 잘못된 부분을 지우고, 종료할 때 정상적으로 닫는 일을 이 스레드들이 한다. 기본값은 디렉토리당 1개인데 파티션이 많으면 언클린 셧다운 이후의 복구 재시작 시간이 몇 시간씩 차이 난다. 시작과 종료 때만 쓰이는 스레드이므로 넉넉히 할당해 병렬화하는 편이 낫다. 값이 디렉토리별이라는 점도 놓치기 쉽다. 8로 잡고 log.dirs에 경로가 3개면 전체 24개다.
auto.create.topics.enable은 기본값이 켜져 있고, 프로듀서가 쓰기 시작하거나 컨슈머가 읽기 시작하거나 클라이언트가 메타데이터를 요청하기만 해도 토픽이 생긴다. 문제는 토픽을 만들지 않고 존재 여부만 확인할 방법이 없어진다는 것이다. 명시적으로 관리하겠다면 false로 둔다.
delete.topic.enable을 false로 두면 토픽 삭제를 막는다. 카프카에서 토픽 삭제는 되돌릴 수 없고 정말 삭제할 것인지 확인하는 절차도 없다.
auto.leader.rebalance.enable은 선호 리더 선출 쪽에서 본다.
토픽 기본값
새로 생성되는 토픽에 적용되는 기본값도 브로커 설정으로 잡는다. 토픽별로 재정의하려면 관리 툴이 필요하다.
num.partitions는 기본 1이다. 늘리기는 되고 줄이기는 안 되므로 이 값보다 적은 파티션이 필요하면 직접 토픽을 만들어야 한다default.replication.factor와min.insync.replicas는 최소 인-싱크 레플리카 쪽에 있다log.retention.ms,log.retention.bytes,log.segment.bytes,log.roll.ms는 보존과 로그 세그먼트 쪽에 있다message.max.bytes는 메시지와 배치 쪽에 있다
하드웨어가 정하는 상한
설정을 아무리 잘 잡아도 하드웨어가 상한을 정한다. 카프카 자체는 특정한 하드웨어 구성을 요구하지 않지만 성능 때문에 감안할 것이 있다.
디스크 처리량이 클라이언트 성능에 가장 큰 영향을 준다. 프로듀서는 최소 하나의 브로커가 커밋되었다고 응답할 때까지 기다리므로, 디스크 쓰기가 빠를수록 쓰기 지연이 줄어든다. SSD는 탐색과 접근 시간이 압도적으로 짧아서 클라이언트 연결이 많을 때 유리하고, HDD는 같은 가격에 용량이 많아서 자주 쓰지 않는 데이터를 아주 많이 저장할 때 유리하다. HDD를 쓴다면 데이터 디렉토리를 여러 개 잡거나 RAID로 성능을 올린다.
디스크 용량은 보존 기간에서 나온다. 하루 1TB를 받아 1주일 보존하면 최소 7TB이고, 트래픽 변동과 다른 파일을 감안해 최소 10%는 여유를 둔다.
메모리는 힙보다 페이지 캐시가 중요하다. 카프카 자체는 JVM 힙을 많이 필요로 하지 않아서 초당 15만 개, 200MB를 처리하는 브로커가 5GB 힙 정도를 쓴다. 나머지 시스템 메모리는 페이지 캐시로 쓰인다. 컨슈머는 보통 파티션 끝에서 방금 쓰인 메시지를 읽으므로 디스크까지 가지 않고 페이지 캐시에서 읽는 것이 최적이고, 캐시에 쓸 메모리를 늘리면 컨슈머 성능이 오른다. 카프카를 다른 애플리케이션과 같은 서버에서 돌리지 말라는 권고가 여기서 나온다. 페이지 캐시를 나눠 쓰면 컨슈머 성능이 떨어진다.
네트워크에는 카프카 특유의 불균형이 있다. 다수의 컨슈머를 동시에 지원하므로 들어오는 양보다 나가는 양이 훨씬 크다. 프로듀서가 초당 1MB를 써도 컨슈머가 여럿 붙고 클러스터 내부 복제와 미러링까지 겹치면 나가는 쪽이 몇 배가 된다. 네트워크 인터페이스가 포화되면 내부 복제가 밀려서 클러스터가 취약한 상태에 빠지므로, 최소 10GB 이상을 처리하는 NIC가 권장된다.