02. 카프카 설치하기

Last updated - 2025년 06월 19일 Edit Source

카프카를 설치하고 간단한 설정 작업을 통해 실습하는 시간을 가져보자. 브로커의 메타 데이터를 저장하기 위해 사용되는 아파치 주키퍼에 대한 설치 또한 진행한다.



# 주키퍼

  • 설정 정보 관리, 이름 부여, 분산 동기화, 그룹 서비스를 제공하는 중앙화된 서비스
    • 카프카 클러스터의 메타 데이터
    • 컨슈머 클라이언트에 대한 정보

# 주키퍼 앙상블

  • 주키퍼 앙상블(ZooKeeper Ensemble)
  • 주키퍼는 고가용성을 보장하기 위해 앙상블이라는 클러스터 단위로 작동하도록 설계됨
  • 주키퍼의 부하 분산 알고리즘 때문에 앙상블은 홀수 개의 서버 (e.g. 3, 5, 7 …) 를 가지는 것이 권장
    • 주키퍼가 요청에 응답하려면 앙상블 멤버(쿼럼, quorum)의 과반 이상이 작동하고 있어야하기 때문

# 주키퍼 앙상블 크기 결정

  • 5개의 노드 크기 고려
    • 앙상블 설정을 변경할 수 있게 하려면, 1번에 1대의 노드를 정지 → 설정 변경 → 재시작 과정 필요
    • 앙상블이 2대 이상의 노드 정지를 받아낼 수 없으면 정비 작업 위험
  • 9대 이상의 노드 사용 권장 ❌
    • 합의(consensus) 프로토콜 특성상 성능이 내려가기 시작하기 때문
  • 클라이언트 연결이 너무 많아서 5대 / 7대 노드가 부하를 감당하기 힘든 상황
    • 옵저버 노드를 추가하여 읽기 전용 트래픽 분산 시도

# 주키퍼 설정 파일

주키퍼 서버 앙상블 구성 시 필요한 요소

  1. 각 서버는 공통된 설정 파일 사용 (앙상블에 포함된 모든 서버의 목록 포함되어있음)
  2. 각 서버는 데이터 디렉토리에 자신의 ID 번호를 지정하는 myid 파일 가지고 있어야함
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 공통 설정 파일

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
initLimit=20
syncLimit=5
server.1=zoo1.example.com:2888:3888
server.2=zoo2.example.com:2888:3888
server.3=zoo3.example.com:2888:3888
  • initLimit : 파티션 팔로워 - 리더 연결할 수 있는 최대 시간 (초기화 제한 시간)
    • 이 시간 동안 리더와 연결 못하면 초기화 실패
  • syncLimit : 파티션 팔로워 - 리더 연결할 수 있는 최대 시간 (동기화 제한 시간)
    • 이 시간 동안 리더와 연결 못하면 동기화 풀림
  • tickTime : 밀리초
    • e.g. initLimit Time = 20 * 2000ms = 40000ms = 40s
  • server.{X}={hostname}:{peerPort}:{leaderPort}
    • X : 서버 ID (0부터 시작할 필요 ❌, 순차적 부여될 필요 ❌)
    • hostname : 서버의 호스트명, IP 주소
    • peerPort : 앙상블 내부 서버들이 통신할때 사용하는 TCP 포트번호
    • leaderPort : 리더를 선출하는데 사용되는 TCP 포트번호
  • clientPort : 클라이언트는 해당 포트로 앙상블에 연결할 수만 있으면 됨
    • 하지만, 앙상블 멤버들은 peerPort, leaderPort, clientPort 모두 사용해서 서로 통신할 수 있어야함

한 대의 서버에서 주키퍼 앙상블 테스트

  • localhost:peerPort:leaderPort
    • peerPort, leaderPort에 서로 다른 포트를 할당
    • 하나의 서버에서 주키퍼 앙상블 테스트 가능
  • 각각의 주키퍼 인스턴스에 서로 다른 dataDir, clientPort 할당
    • 추가적인 zoo.cfg 파일 생성 필요



# 카프카 설치


# macOS 설치

필자는 macOS 환경에서 실습을 진행했다. homebrew 사용을 선호하지 않아서 카프카 홈페이지의 2.13-2.8.0을 설치했다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 주키퍼 서버 시작
{path}/bin/zookeeper-server-start.sh -daemon {path}/config/zookeeper.properties

# 카프카 서버 시작
{path}/bin/kafka-server-start.sh -daemon {path}/config/server.properties

# 주키퍼 작동 테스트
telnet localhost 2181

# 텔넷 접속 이후 
srvr

# 토픽 생성 및 확인

토픽 생성 및 확인

1
2
3
4
5
# 브로커에 토픽-파티션 생성
{path}/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --replication-factor 1 --partitions 1 --topic test

# 생성된 토픽 내용 확인
{path}/bin/kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic test

토픽에 메세지 작성

1
2
3
4
5
6
7
# 프로듀서 메세지 발행
{path}/bin/kafka-console-producer.sh --bootstrap-server localhost:9092 --topic test

# 콘솔창 진입
Test Message 1
Test Message 2
^C

토픽에 저장된 메세지 읽기

1
2
3
4
5
6
7
8
# 컨슈머 메세지 소비
{path}/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning

# 콘솔창에 표시되는 내용
Test Message 1
Test Message 2
^C
Processed a total of 2 messages

CLI 유틸리티 주키퍼 연결 지원 중단

  • --zookeeper 연결 문자열 지원 중단
  • --bootstrap-server 사용하여 카프카 브로커에 직접 연결
  • 클러스터 운영중이라면 브로커의 {호스트명}:{포트번호} 사용 가능



# 브로커 설정

  • 카프카는 거의 모든 구성을 제어하고 튜닝 가능
  • 다만, 특정 활용 사례가 아닌 경우, 바꿀 일이 없는 튜닝 관련 옵션이 다수
  • 우선 기본값으로 사용해도 무방

KRaft 모드 설정은 6장 참조


# 핵심 브로커 매개변수

  • 단일 서버에서 단독으로 실행되는 브로커라면 상관없음
  • 위의 경우를 제외하면 봐야만 하는 브로커의 설정 매개변수들이 있음
    • 브로커의 기본적인 설정 담당
    • 다른 브로커들과 클러스터 모드로 작동시키려면 변경 필요 🟢

(1) broker.id

  • 카프라 브로커의 정숫값 식별자
  • default : 0
  • 클러스터 안의 각 브로커별로 전부 달라야 함
  • 호스트별로 고정된 값을 사용하는 것이 강력하게 권장됨
    • e.g. host1.example.com / host2.example.com 인 경우 broker.id = 1 / broker.id = 2

(2) listeners

  • {프로토콜}://{호스트이름}:{포트}
    • e.g. PLAINTEXT://localhost:9092 , SSL://:9091
    • 일반적인 보안 프로토콜이 아니라면 listener.security.protocol.map 재설정 필요
  • 호스트이름이 0.0.0.0 인 경우
    • 모든 네트워크 인터페이스로부터 연결 받게됨
  • 호스트이름이 빈값 인 경우
    • 기본 인터페이스에 대해서만 연결 받게됨
  • 1024 미만의 포트번호 사용할 경우
    • 루트 권한으로 카프카 실행 필요 🟢
    • 권장 ❌

(3) zookeeper.connect

  • 브로커의 메타데이터가 저장되는 주키퍼의 위치를 가리킴
    • e.g. 로컬호스트의 2181번 포트에서 작동중인 주키퍼를 사용하는 경우 localhost:2181
  • {호스트이름}:{포트}/{경로}
    • 호스트이름 : 주키퍼 서버의 호스트이름, IP 주소
    • 포트 : 주키퍼 클라이언트 포트 번호
    • /{경로} : optional, 카프카 클러스터의 chroot 환경으로 사용될 주키퍼 경로
      • 미지정 시 루트 디렉토리 사용됨
      • chroot가 존재하지 않는 경로일 시, 브로커가 시작될 때 자동으로 생성됨

chroot 경로 사용 이유

  • 다른 애플리케이션 (다른 카프카 클러스터 포함)과 충돌할 일 없이 주키퍼 앙상블을 공유해서 사용할 수 있기 때문
  • 같은 앙상블에 속하는 다수의 주키퍼 서버를 지정하는 것이 좋음
    • 특정 서버에 장애 발생 시, 카프카 브로커가 같은 주키퍼 앙상블의 다른 서버에 연결 가능 🟢

(4) log.dirs

  • 카프카는 모든 메세지를 로그 세그먼트(log segment) 단위로 묶어서 log.dir에 지정된 디스크 디렉토리에 저장함
  • 다수의 디렉토리 지정 원하는 경우, log.dirs 사용하는 것이 좋음
    • log.dirs 미 설정시 log.dir 사용됨
  • log.dirs는 쉼표로 구분된 로컬 시스템 경로의 목록
  • 1개 이상의 경로 지정 시, 브로커는 가장 적은 수의 파티션이 저장된 디렉토리에 새 파티션을 저장
  • 같은 파티션에 속하는 로그 세그먼트는 동일 경로에 저장
  • 사용된 디스크 용량 기준이 아닌 저장된 파티션 수 기준으로 새 파티션의 저장 위치를 배정함
    • 다수의 디렉토리에 균등한 양의 데이터가 저장되지 않는다는 의미

(5) num.recovery.threads.per.data.dir

  • 카프카는 설정 가능한 스레드 풀을 사용하여 로그 세그먼트 관리
    • 브로커 정상 시작 시, 각 파티션의 로그 세그먼트 파일 오픈
    • 브로커 장애 발생 후 재시작 시, 각 파티션의 로그 세그먼트 검사 후, 잘못된 부분 삭제
    • 브로커 종료 시, 로그 세그먼트를 정상적으로 클로즈
  • default : 하나의 로그 디렉토리에 하나의 스레드만 사용
    • 이 스레드들은 브로커가 시작될 때, 종료될 때만 사용됨
    • 작업을 병렬화하기 위해 많은 수의 스레드를 할당해주는 것이 좋음
  • 브로커에 많은 파티션이 저장된 경우, 해당 설정에 따라 언클린 셧다운(unclean shutdown) 이후 복구를 위한 재시작 시간이 몇 시간씩 차이가 날 수 있음
  • 이 설정값을 잡을 때 log.dirs에 지정된 로그 디렉토리별 스레드 수임을 명심
  • e.g. num.recovery.threads.per.data.dir = 8, log.dirs에 지정된 경로 수 = 3
    • → 전체 스레드 수는 24개

(6) auto.create.topics.enable

  • default : 아래의 상황에서 브로커가 토픽을 자동 생성함
    • 프로듀서가 토픽에 메세지 작성 시작했을 때
    • 컨슈머가 토픽으로부터 메세지 읽기 시작했을 때
    • 클라이언트가 토픽에 대한 메타데이터 요청 시
  • 문제점 : 카프카에 토픽을 생성하지 않고 존재 여부만을 확인할 방법 ❌
  • 토픽 생성을 명시적으로 관리할 경우 해당 값을 false로 설정 가능 🟢
  • e.g. auto.create.topics.enable = false

(7) auto.leader.rebalance.enable

  • 모든 토픽의 리더 역할이 하나의 브로커에 집중됨으로써 카프카 클러스터의 균형이 깨지는 순간 발생 가능 🟢
  • 해당 설정 활성화 시, 가능한 리더 역할이 균등하게 분산되도록 하여 위 상황 방지
  • 파티션의 분포 상태를 주기적으로 확인하는 백그라운드 스레드 시작
    • leader.imbalance.check.interval.seconds 값으로 주기 설정 가능
  • 전체 파티션 중 특정 브로커에 리더 역할이 할당된 파티션 비율이 leader.imbalance.per.broker.percentage 값을 넘기면 파티션의 선호 리더 리밸런싱 발생
    • 해당 기능은 5장의 선호 리더 선출에서 다시 설명

(8) delete.topic.enable

  • 클러스터의 토픽을 임의로 삭제하지 못하게 막을 때
  • e.g. delete.topic.enable = false
    • 토픽 삭제 기능 막음



# 파티션 수 결정

파티션은 카프카 클러스터 내부에서 토픽의 크기가 확장되는 방법

  • 브로커 추가 시, 클러스터 전체에 걸쳐 메세지 부하가 고르게 분산되도록 파티션 개수를 잡아주는 것이 중요
  • 보통 토픽당 파티션 개수클러스터 내 브로커의 수와 맞추거나 배수로 설정
    • 파티션이 브로커들 사이에 고르게 분산되도록 할 수 있음
    • e.g. 10개의 파티션으로 이루어진 토픽이 10개의 호스트로 구성된 카프카 클러스터에서 작동 중이며 각 파티션의 리더 역할이 10개 호스트에 고르게 분산되어있다면 최적의 처리량이 나올 것
      • 토픽 여러개 생성 이외에 다른 방법으로 메세지 부하 분산이 가능해서 필수 사항은 아님

파티션 수는 어떻게 결정? 여러가지 사항을 고려하자

  • 토픽에 대해 달성하고자 하는 처리량이 대략 어느정도?
  • 단일 파티션에 대해 달성하고자 하는 최대 읽기 처리량은 어느정도?
    • 1개의 파티션은 항상 1개의 컨슈머만 읽을 수 있음 (컨슈머 그룹 기능 미사용 시에도, 컨슈머는 해당 파티션의 모든 메세지를 읽도록 되어있음)
  • 각 프로듀서가 단일 파티션에 쓰기 작업하는 최대 속도에 대해서도 고려할 수 있음
    • 다만, 프로듀서가 컨슈머에 비해 훨씬 더 빠른 것이 보통
    • 이 작업은 건너뛰어도 괜찮음

키값을 기준으로 선택된 파티션에 메세지를 전송하는 경우, 추후 파티션 추가 시 복잡

  • 이 경우 현재의 사용량이 아닌 미래의 사용량 예측값을 기준으로 처리량 계산
  • 각 브로커에 배치할 파티션 수, 브로커별 사용 가능 디스크 공간, 네트워크 대역폭 고려
  • 과대 추산 피하기
    • 각 파티션은 브로커의 메모리와 다른 자원들을 사용함
    • 메타데이터 업데이트, 리더 역할 변경 등 여러 부분에서 걸리는 시간 증가하게됨
  • 데이터를 미러링 할 예정이라면, 미러링 설정의 처리량 또한 고려 필요
    • 미러링 구성에서 큰 파티션이 병목 구간인 경우 많음
  • 클라우드 서비스 사용 시, VM이나 디스크에 초당 입출력(IOPS, input/output operations per second) 제한 걸려있는지도 확인 필요
    • IOPS 상한선이 설정되어 있을 수 있음
    • 파티션 수가 너무 많으면 병렬 처리 때문에 IOPS 양이 증가할 수 있음

결론 : 파티션은 많아야 하지만, 너무 많으면 안된다

  • 토픽의 목표 처리량, 컨슈머의 예상 처리량에 대한 추정값이 있다면 필요한 파티션 수 계산 가능
    • e.g. 주어진 토픽을 읽는 속도가 초당 1GB를 원해요
      • 컨슈머 1개가 초당 50MB만 처리가 가능한 상황
      • 그렇다면 최소한 20개의 파티션이 필요하다고 예측 가능
      • 20개의 컨슈머가 동시에 하나의 토픽을 읽어서 초당 1GB 읽기 가능
  • 상세 정보 없는 경우
    • 링크드인 경험 상, 디스크 내부에 저장되어 있는 파티션의 용량을 6GB 미만으로 유지하는 것이 대체로 결과가 좋았음
    • 작은 크기에서 점진적 확장이 반대보다 더 쉽다



# 토픽별 기본값

  • 카프카 브로커 설정 → 새로 생성되는 토픽에 적용되는 수많은 설정의 기본값 지정
  • 토픽별 설정값을 재정의하고 싶으면 관리툴 사용 필요. 해당 내용은 12장에서 학습

(1) num.partitions

  • 새로운 토픽이 생성될 때 몇 개의 파티션을 갖게 되는지 결정
  • default : 1
    • 자동 토픽 생성 기능이 활성화되어 있을 때 사용됨
    • 자동 토픽 생성 기능 역시 default : true
  • 토픽의 파티션 개수 늘리기는 🟢 줄이기는 불가능 ❌
    • 토픽이 num.partitions에 지정된 것보다 더 적은 수의 파티션을 가져야 한다 → 직접 토픽을 생성할 필요가 있다

(2) default.replication.factor

  • 자동 토픽 생성 기능 활성화 시, 새로 생성되는 토픽의 복제 팩터를 결정함
    • 아래의 설정 값은 하드웨어 장애 등 카프카 외부 요인으로 인한 장애가 발생하지 않아야 하는 카프카 클러스터를 운영하는 상황에서의 권장사항
  • 복제 팩터 값은 min.insync.replicas 설정값보다 최소한 1 이상 크게 잡아줄 것을 강력 권장
  • 복제 팩터 값을 min.insync.replicas 설정값보다 2 큰 값으로 잡는 경우
    • 내고장성 있는 설정 원함 + 충분한 하드웨어를 사용할 수 있는 충분히 큰 울러스터 운영중일 때
    • 이것을 보통 RF++ 라고 함
    • 레플리카 셋 안에 일부러 정지시킨 레플리카, 예상치 않게 정지된 레플리카가 동시에 하나씩 발생해도 장애가 발생하지 않기 때문에 권장됨
    • 즉, 일반적인 클러스터의 경우 파티션별로 최소한 3개의 레플리카를 가져야 한다는 이야기
      • e.g. 네트워크 스위치나 디스크 같은 하드웨어에 장애 발생 시, 혹은 카프카나 운영체제를 롤링 업데이트 하는 중에 문제가 발생해도 적어도 1개의 레플리카는 정상 작동 중이라는 것을 보장 가능

(3) log.retention.ms

  • 카프카가 얼마나 메세지를 보존해야 하는지 지정할 때 사용하는 설정 (시간 기준 설정)
  • default : log.retention.hours = 168을 보통 사용 → 168시간 (1주일)
    • log.retention.ms → 가장 권장 🟢
    • log.retention.minutes
    • log.retention.hours
  • 1개 이상의 설정이 정의된 경우 더 작은 단위 설정값이 우선순위 가짐
    • log.rentention.ms에 설정된 값은 언제나 적용됨을 보장할 수 있음. 그래서 권장됨

시간 기준 보존, 마지막 수정 시각

  • 시간 기준 보존
    • 디스크에 저장된 각 로그 세그먼트 파일의 마지막 수정 시각(mtime) 기준으로 작동
    • 이 값은, 해당 로그 세그먼트가 닫힌 시각을 의미
    • 이 값은, 해당 파일에 저장된 마지막 메세지의 타임스탬프를 의미
    • 하지만, 관리 툴을 사용하여 브로커 간 파티션을 이동시킨 경우 이 값은 정확하지 않음
    • → 파티션이 지나치게 오래 보존되는 결과 초래 가능

(4) log.retention.bytes

  • 카프카가 메세지를 보존할 수 있는 용량 (크기 기준 설정)
  • 파티션 단위로 적용됨
    • e.g. 8개의 파티션을 가진 토픽, log.retention.bytes = 1GB → 토픽 최대 저장 용량 8GB
  • 모든 보존 기능은 토픽 단위가 아닌 파티션 단위로 작동함
    • log.retention.bytes 설정 사용중인 상태에서 토픽의 파티션 수를 증가 → 보존되는 데이터의 양도 함께 늘어난다는 의미
  • log.retention.bytes = -1
    • 데이터 영구 보존

크기와 시간을 기준으로 보존 설정

  • log.retention.bytes, log.retention.ms 두 설정 모두 준 경우
    • 하나의 조건만 성립해도 메세지가 삭제될 수 있음
    • 의도치 않은 데이터 유실 방지를 위해 크기 기준 설정 / 시간 기준 설정 중 하나만 선택하기를 권장

(5) log.segment.bytes

  • log.retention.bytes, log.retention.ms는 로그 세그먼트에 적용되는 로그 보존 설정
    • 메세지 각각에 적용되는 것이 아닙니다 !
  • 카프카 브로커에 쓰여진 메세지는 해당 파티션의 현재 로그 세그먼트의 끝에 추가됨
    • 로그 세그먼트 크기가 log.segment.bytes에 지정된 크기에 가까워졌음
    • 브로커는 기존 로그 세그먼트를 닫고 새로운 로그 세그먼트를 염
    • 로그 세그먼트가 닫히기 전까지 만료/삭제의 대상이 되지 않음
  • default : 1GB
  • 작은 로그 세그먼트 크기
    • 더 자주 닫고 새로 할당한다는 의미
    • 디스크 쓰기의 전체적인 효율성 감소를 의미

토픽에 메세지가 뜸하게 주어지는 상황

  • 로그 세그먼트 크기 조절이 중요할 수 있음
  • e.g. 토픽에 들어오는 메세지가 하루 100MB + log.segment.bytes 기본값 1GB
    • 세그먼트 하나 채울때까지 10일 걸림
    • 로그 세그먼트가 닫히기 전까지 메세지는 만료되지 않음
    • log.retention.ms = 604800000(1주일)로 잡힌 경우
    • 닫힌 로그 세그먼트가 만료될 때까지 실제로는 최대 17일치 메세지가 저장되어 있을 수 있음
      • 로그 세그먼트 닫힐 때까지 채우기 10일 + 보존기간 7일

타임스탬프 기준 오프셋 찾기

  • 로그 세그먼트 크기는 타임스탬프 기준 오프셋 찾는 기능에도 영향 끼침
    • (1) 클라이언트가 특정 타임스탬프 기준으로 파티션의 오프셋 요청
    • (2) 카프카는 해당 시각에 쓰여진 로그 세그먼트 찾음
    • (3) 로그 세그먼트 파일 생성 시각 + 마지막 수정 시각을 이용하여 작업
      • 주어진 타임스탬프보다 생성된 시각은 더 이름
      • 마지막으로 수정된 시각은 더 늦은 파일을 찾음
    • (4) 로그 세그먼트의 맨 앞에 있는 오프셋이 응답으로 리턴됨
      • 맨 앞에 있는 오프셋은 로그 세그먼트 파일의 이름이기도 함

(6) log.roll.ms

  • 파일이 닫혀야 할 때까지 기다리는 시간을 지정하는 매개변수
    • 로그 세그먼트 파일이 닫히는 과정을 해당 매개변수로도 제어 가능하다는 의미
  • default : 설정 X
    • 기본적으로 세그먼트 파일을 닫는 작업은 크기 기준으로만 이루어지는 것이 기본값

시간 기준 세그먼트 사용 시 디스크 성능

  • 다수의 로그 세그먼트가 동시에 닫힐 때, 디스크 성능에 대한 고려 필요
  • 여러 개의 파티션이 로그 세그먼트 크기 제한에 도달하지 못하는 경우 발생 가능
    • 브로커가 시작되는 시점부터 시간제한이 계산됨
    • 크기가 작은 파티션을 닫는 작업 역시 한꺼번에 이루어지기 때문

(7) min.insync.replicas

  • default : 1
  • 데이터 지속성 위주로 클러스터 설정 시, 해당 값을 2로 잡는 경우
    • 최소한 2개의 레플리카가 최신 상태로 프로듀서와 동기화되도록 가능 🟢
    • 프로듀서의 ack 설정을 all로 잡아주는 것과 함께 사용됨
    • 프로듀서의 쓰기 작업이 성공하기 위해 최소한 두 개의 레플리카 (리더 하나, 팔로워 하나) 가 응답하도록 할 수 있음
  • 이는 아래 상황에서 데이터 유실 방지 가능
    • (1) 리더가 쓰기 작업에 응답
    • (2) 리더에 장애 발새
    • (3) 리더 역할이 최근에 성공한 쓰기 작업 내역을 복제하기 전의 다른 레플리카로 옮겨짐
  • min.insync.replicas 설정 ❌인 경우
    • 프로듀서는 쓰기 작업이 성공했다고 착각
    • 실제로는 메세지가 유실
  • min.insync.replicas 설정값 높게 잡은 경우
    • 오버헤드 발생하여 성능 감소하는 부작용 발생
  • 몇 개의 메세지 유실 정도는 괜찮고, 높은 처리량을 받아내야 하는 클러스터의 경우
    • 기본값인 1에서 변경하지 않는 것을 권장

(8) message.max.bytes

  • 카프카 브로커는 쓸 수 있는 메세지 최대 크기를 제한함
  • default : 1,000,000 (1MB)
  • 프로듀서가 message.max.bytes 보다 큰 크기의 메세지 보내려고 시도 → 브로커는 메세지를 거부하고 에러 리턴
  • 브로커에 설정된 모든 바이트 크기와 마찬가지로, 압축된 메세지의 크기를 기준으로 함
    • 프로듀서는 압축된 결과물이 message.max.bytes 보다 작기만 하면 압축 전 기준 이 값보다 훨씬 큰 메세지도 보낼 수 있는 것
  • 허용 가능 메세지 크기 증가 → 성능에 큰 영향
    • 메세지가 커지는 만큼 네트워크 연결, 요청 처리하는 브로커 스레드의 요청당 작업 시간 증가
    • 디스크에 써야하는 크기 증가 → I/O 처리량에 영향 끼침
    • 개체 저장소(blob store), 계층화된 저장소(tiered storage) 솔루션으로 디스크 용량 문제 해결할 수 있음

메세지 크기 설정 조정

  • 카프카 브로커에 설정되는 메세지 크기
    • 컨슈머 클라이언트의 fetch.message.max.bytes 설정과 맞아야 함
  • fetch.message.max.bytes < message.max.bates 인 경우
    • 컨슈머는 지정된 fetch.message.max.bytes 값보다 더 큰 메세지를 읽는데 실패
    • 읽기 작업 진행 중단
    • 이는 클러스터 브로커의 replica.fetch.max.bytes 설정에도 동일하게 적용됨



# 하드웨어 선택

  • 카프카 자체는 특정한 하드웨어 구성 요구 ❌
  • 다만 성능 때문에 디스크 처리량, 디스크 용량, 메모리, 네트워크, CPU 감안 필요
  • 카프카를 매우 크게 확장할 경우
    • 업데이트 되어야 할 메타데이터의 양 때문에 하나의 브로커가 처리할 수 있는 파티션의 수에도 제한 생길 수 있음 🟢

# 디스크 처리량

브로커 디스크의 처리량

  • 로그 세그먼트 저장
  • 클라이언트의 성능에 가장 큰 영향을 끼침
  • 프로듀서 클라이언트가 메세지 전송을 성공했다고 결론 내리기 이전, 최소한 1개 이상의 브로커가 메세지가 커밋되었다고 응답을 보낼 때까지 대기하게 됨
    • 디스크 쓰기 (↑) → 쓰기 지연 (↓)

여러 저장장치 선택 가이드

  • SSD : 탐색과 접근에 들어가는 시간 압도적으로 짧음. 최고의 성능
  • HDD : 더 싸고 같은 가격에 더 많은 용량 제공
    • 데이터 디렉토리 여러 개로 잡기
    • RAID (Redundant Array of Independent Disks) 구성을 통해 브로커에 여러 대의 HDD를 사용하여 성능 향상시키기 가능
  • SAS (Serial Attached SCSI), SATA (Serial ATA) 같은 특정 드라이브 기술, 드라이브 컨트롤러의 성능 등도 처리량에 영향 끼침
  • 많은 수의 클라이언트 연결을 받아내야하는 경우 → SSD 승
  • 자주 쓸 일이 없는 데이터를 굉장히 많이 저장해야 하는 클러스터의 경우 → HDD 드라이브 승



# 디스크 용량

  • 특정 시점에 얼마나 많은 메세지들이 보존되어야 하는지에 따라 결정
  • e.g. 브로커가 하루에 1TB 트래픽 받을 것으로 예상 + 받은 메세지 1주일간 보존
    • 로그 세그먼트를 저장하기 위한 저장 공간이 최소 7TB 필요
    • 트래픽 변동/증가 대비 예비 공간, 저장해야 할 다른 파일 감안하여 최소 10% 가량 오버헤드 고려

디스크 저장 용량은 카프카 클러스터의 크기를 변경, 확장하는 시점에 고려할 중요한 요소

  • 클러스터에 들어오는 전체 트래픽 → 토픽별 다수의 파티션을 잡아서 클러스터 전체에 균형있게 분산 가능 🟢
  • 단일 브로커의 용량이 충분하지 못하면 → 브로커 추가하여 전체 용량 증대 가능 🟢
  • 필요한 디스크 용량은 클러스터에 설정된 복제 방식에 따라서도 달라짐



# 메모리

프로듀서가 막 추가한 메세지를 바로 뒤에서 쫓아오는 식으로 카프카 컨슈머가 파티션의 맨 끝에서 메세지를 읽는 것이 보통

  • 최적의 작동 : 시스템의 페이지 캐시에 저장된 메세지들을 컨슈머가 읽어오는 것
    • 브로커가 디스크로부터 메세지를 다시 읽어오는 것보다 더 빠르게 읽어오는 것
  • 시스템에 페이지 캐시로 사용할 메모리를 추가 할당
    • 컨슈머 클라이언트 성능 향상 (↑)

카프카 자체는 JVM에 많은 힙 메모리를 필요로 하지 않음

  • e.g. 1s 당 150,000개의 메세지에 200MB의 데이터 속도를 처리하는 브로커
    • 5GB 힙 정도 사용
  • 시스템 메모리의 나머지 영역은 페이지 캐시로 사용됨
    • 시스템이 사용중인 로그 세그먼트를 캐시하도록 함 → 카프카의 성능 향상 (↑)
    • 카프카를 하나의 시스템에서 다른 애플리케이션과 함께 운영하는 것을 권장하지 않는 이유
    • 페이지 캐시를 나눠서 쓰게 됨 → 카프카 컨슈머 성능 저하 (↓)



# 네트워크

사용 가능한 네트워크 대역폭 → 카프카가 처리할 수 있는 트래픽 최대량 결정

  • 디스크 용량과 함께 클러스터의 크기를 결정하는 가장 결정적 요인

카프카 특유의 네트워크 불균형 문제

  • 카프카가 다수의 컨슈머를 동시 지원함
  • 이때 인입되는 네트워크 사용량, 유출되는 네트워크 샤용량 사이에 불균형 생김
  • e.g. 프로듀서가 주어진 토픽에 초당 1MB 쓰기 작업 중
    • 해당 토픽에 컨슈머가 다수 붙음으로써 유출되는 네트워크 사용량 훨씬 증가
    • 클러스터 내부의 복제, 미러링 등 요구 조건이 많아짐
  • 네트워크 인터페이스가 포화상태에 빠진 경우
    • 클러스터 내부 복제작업이 밀려서 클러스터가 취약한 상태에 빠짐
    • 네트워크 문제 방지 위해 최소한 10GB 이상 처리 가능한 네트워크 인터페이스 카드(NIC) 사용 권장



# CPU

Comment