카프카는 어떻게 신뢰성을 보장할까?
1️⃣ 카프카는 파티션 안의 메시지들 간에 순서를 보장한다.
메시지 A 다음에 B가 쓰여졌다면 동일한 프로듀서가 동일한 파티션에 썻을 경우 B의 오프셋이 A보다 큰 것을 보장한다.
2️⃣ 클라이언트가 쓴 메시지는 모든 in-sync replica의 파티션에 쓰여진 뒤에야 commit된 것으로 간주한다.
굳이 디스크에 flush될 필요까지는 없으며 프로듀서의 commit 정책을 지정할 수 있다. (acks)
- 완전히 commit된 다음 응답
- 리더에게 쓰여진 다음 응답
- 네트워크로 전송된 다음 바로 응답
3️⃣ commit된 메시지들은 최소 1개의 작동 가능한 replica가 남아 있는 한 유실되지 않는다.
4️⃣ 컨슈머는 commit된 메시지만 읽을 수 있다.
메시지를 저장하는 데 있어서 신뢰성과 일관성이 우선이냐, 아니면 가용성, 높은 처리량, 낮은 지연, 하드웨어 비용과 같은 다른 고려사항이 우선인지의 따라서 트레이드오프가 발생하게 된다.
- 즉 설정 매개변수를 조절함으로써 어느 정도 신뢰성이 필요한지 결정하는게 중요하다.
복제
카프카의 복제 메커니즘은 파티션별로 다수의 레플리카를 유지한다는 특성과 함께 카프카의 신뢰성 보장의 핵심
- 하나의 메시지를 여러 개의 레플리카에 씀으로써 카프카는 크래시가 나더라도 메시지 지속성을 유지한다.
각 카프카 토픽은 파티션으로 이루어지며, 하나의 파티션은 하나의 디스크에 저장된다.
- 모든 이벤트들은 리더 레플리카에 쓰여지며 읽혀지지만 옵션을 통해서 네트워크 성능 최적화를 위해 변경될 수도 있다. (대체로 리더)
- 모든 리더가 작동 불능 상태가 되면, in-sync replica 중 하나가 새 리더가 된다.
레플리카는 파티션의 리더/팔로워 레플리카가 특정 시간동안 아래 조건을 만족하는 경우 in-sync 상태라고 간주
- 주키퍼로 하트비트를 전송
- 리더로부터 메시지를 읽기
- 랙이 없었던 적이 최소 한번은 있을 때
레플리카와 주키퍼 사이의 연결이 끊어지거나, 새 메시지를 읽어오길 중단하거나, 특정 시간동안의 업데이트 내역을 따라오지 못하면 out of sync 상태로 간주
- 주키퍼와 다시 연결되어 리더 파티션에 쓰여진 가장 최근 메시지까지 따라잡으면 다시 in-sync 레플리카가 된다.
- 오랜 기간동안 down 되어 있었을 경우 시간이 좀 걸릴 수 있다.
이전에는 최대 요청 크기가 커서 JVM 힙도 크게 사용중인 경우 빈번하게 in-sync replica ↔️ out-of-sync replica 상태를 빠르게 왔다갔다 했다.
- 튜닝을 안하면 브로커의 가비지 수집 시간이 오래걸려 순간적으로 주키퍼와의 연결이 끊어지기 때문
- 요즘은 이런 문제가 드물지만, 여전히 큰 메시지를 사용할 경우 튜닝이 필요하다.
동기화가 늦어지면 in-sync 레플리카는 프로듀서와 컨슈머를 느리게 만들 수 있다.
- 프로듀서와 컨슈머는 메시지가 커밋되기 전, 모든 in-sync 레플리카가 해당 메시지를 받을 때까지 기다려야 하기 때문이다.
- out-of-sync 레플리카가 되어서 in-sync 레플리카 수가 줄어들면 파티션의 실질적인 복제 팩터가 줄어들면서 중단 시간이 길어지거나 데이터가 유실될 위험성은 높아진다.
브로커 설정
메시지 저장 신뢰성과 관련된 카프카의 작동을 변경시키는 브로커의 설정 매개변수가 있다.
- 이 설정들은 브로커 단위에서 적용되어 시스템 안의 모든 토픽들을 제어할 수도 있고 토픽 단위에서 적용되어 특정 토픽의 작동을 제어할 수 있다.
- 신뢰성이 필요한 토픽과 아닌 토픽을 같은 클러스터에 저장할 수 있다.
복제 팩터
토픽 단위 설정은 replication.factor, 자동으로 생성되는 토픽들에 적용되는 브로커 단위 설정은 default.replication.factor 설정에 잡아둔다.
- 토픽의 복제 팩터가 3이면 각 브로커가 3대의 서로 다른 브로커에 3개 복제된다는 것을 의미 (기본값)
복제 팩터가 N이면 N-1개의 브로커가 중단되더라도 토픽의 데이터를 읽거나 쓸 수 있다.
- 복제 팩터가 클수록 가용성과 신뢰성은 늘어나고 장애가 발생할 가능성은 줄어든다.
- 하지만 최소한 N개의 브로커가 필요하며 N개의 복사본을 저장해야 하므로 N배의 디스크 공간이 필요
토픽 단위로 적절한 레플리카 개수를 지정하기 위한 핵심 고려 사항
가용성
레플리카가 하나뿐인 파티션은 정기적으로 브로커를 재시작하기만 해도 작동 불능에 빠진다.
- 레플리카 수가 많아질수록 가용성은 늘어난다.
지속성
파티션에 레플리카가 하나뿐인데 디스크가 사용 불가능하게 될 경우 해당 파티션의 모든 데이터는 유실된다.
- 각 레플리카는 파티션 안의 모든 데이터의 복사본이라서 서로 다른 장치에 복사본이 많을수록 모든 데이터가 유실될 가능성은 줄어든다.
처리량
레플리카가 추가될 때마다 브로커간 트래픽 역시 늘어난다.
- 특정 파티션에 10Mbps의 속도로 쓸 때 레플리카가 하나라면 복제 트래픽은 발생하지 않지만 레플리카가 N개라면 (N-1) * 10Mbps가 될 것이다.
- 클러스터의 크기와 용량을 산정할 때는 이를 고려해야 한다.
종단 지연
쓰여진 메시지를 컨슈머가 읽을 수 있으려면 모든 in-sync 레플리카에 복제되어 commit 되어야 한다.
- 레플리카 수가 더 많을수록 이들 중 하나가 느려지면 컨슈머까지 함께 느려질 가능성이 높다.
- 특정 브로커가 느려지면 해당 브로커를 사용하는 모든 클라이언트 역시 복제 팩터에 무관하게 느려진다.
비용
더 많은 레플리카를 가질수록 저장소와 네트워크에 들어가는 비용 역시 증가하게 된다.
- 복제 팩터가 줄어들 수록 비용은 줄어들겠지만 동일하게 가용성 역시 줄어들게 되며, 지속성이 저장 장치에 의해 보장될 수 있다.
레플리카의 위치
카프카는 언제나 같은 파티션의 레플리카들을 서로 다른 브로커에 저장한다.
- 같은 파티션의 모든 레플리카들이 같은 랙에 설치되어 있는 브로커들에 저장될 때, 랙 스위치가 오작동 하면 복제 팩터하고는 상관없이 해당 파티션은 사용할 수 없게 된다.
- 랙 단위 사고를 방지하기 위해 브로커들을 서로 다른 랙에 배치한 뒤 broker.rack 브로커 설정 매개변수에 랙 이름을 잡아 줄 것을 권장한다. (파티션의 레플리카들이 서로 다른 랙에 분산 저장되어 가용성을 높일 수 있다.)
언클린 리더 선출
모든 팔로워 레플리카가 장애가 나서 리더 레플리카만 남았는데, 이 상황에서 리더 레플리카가 작동 불능 상태가 되는 경우 어떻게 해야할까?
❌ out-of-sync replica가 새 리더가 될 수 없는 경우
예전 리더 replica가 복귀될 때까지 해당 파티션은 오프라인 상태가 되어 메모리 칩을 교체해야 하는 작업등이 발생하면 몇 시간이 걸릴 수도 있다.
✅ out-of-sync replica가 새 리더가 될 수 있는 경우
새 리더가 동기화를 못 한 사이 예전 리더에 쓰여졌던 모든 메시지들이 유실되고 컨슈머 입장에서의 일관성 역시 어느 정도 깨지게 된다.
- 몇몇 컨슈머들은 예전 리더에 쓰여진 메시지를 읽었겠지만 일부는 같은 오프셋을 할당받은 새 메시지들을 읽게되며, 일부는 둘을 뒤섞인 채로 읽게 된다.
- 예전 리더가 다시 온라인 상태로 복구되어 새 리더의 팔로워가 되는 경우 자신이 가지고 있는 메시지 중에서 현재의 리더가 가지고 있지 않은 메시지들을 삭제하며, 이 메시지들은 이후 아무 컨슈머들도 읽을 수 없다.
unclean.leader.election.enable 설정은 브로커 단위(실제로는 클러스터 단위)에서만 가능하며, 기본값은 false이다.
- true로 설정할 경우 out-of-sync replica가 리더가 될 수 있도록 허용할 경우 데이터 유실과 일관성 깨짐의 위험성이 있다.
- false로 설정할 경우 파티션이 다시 온라인 상태가 될 때까지 원래 리더가 복구되는 것을 기다려야 하는 만큼 가용성은 줄어들게 된다.
운영자 입장에서 극단적인 불용 상황에서 파티션을 사용 가능한 상태로 만들기 위해 데이터 유실을 감수하고 true로 바꾼 뒤 클러스터를 시작한다면, 클러스터가 복구된 뒤 false로 꼭 되돌리자.
최소 in-sync replica
토픽과 브로커 단위 모두 min.insync.replicas 설정에서 잡아줄 수 있다.
토픽당 in-sync 레플리카는 하나만 남을 수도 있는데 카프카가 보장하는 신뢰성에 따르면, 데이터는 ‘모든’ in-sync 레플리카에 쓰여진 시점에서 커밋된 것으로 간주된다.
- ‘모든’이 단 한개의 레플리카를 의미할 수도 있다. (데이터가 유실될 수 있다.)
- ‘모든’의 최소 개수를 지정하는 것이 min.insync.replicas라고 생각하면 된다.
min.insync.replicas 설정 값 > 온라인 되어 있는 레플리카 수 조건의 경우 읽기 전용이 된다.
- 브로커는 더 이상 쓰기 요청을 받을 수 없다.
- 데이터를 전송하고자 시도하는 프로듀서는 NotEnoughReplicasException을 받게 된다.
- 레플리카가 브로커를 재시작 등으로 복구시킨 뒤 리더 레플리카의 상태를 따라잡아서 회복되면 조건이 깨지면서 읽기 전용 상태를 벗어날 수 있다.
레플리카를 in-sync 상태로 유지하기
신뢰성을 낮추는 out-of-sync 레플리카가 되는 조건에 대해서 카프카 클러스터의 민감도를 조절할 수 있는 두 개의 브로커 설정이 있다. (아래 시간 조건을 넘어서는 경우 out-of-sync 상태가 된다.)
1️⃣ zookeeper.session.timeout.ms (v2.5.0 default 6s → 18s)
카프카 브로커가 주키퍼로 하트비트 전송을 멈출 수 있는 최대 시간
- 이 간격 안에만 하트비트를 보내면 주키퍼는 브로커가 죽었다고 판단하지 않으므로 클러스터에서 제외하지도 않는다.
- 가비지 수집이나 네트워크 상황과 같은 무작위적인 변동에 영향을 받지 않을 만큼 높게, 하지만 실제로 작동이 멈춘 브로커가 적시에 탐지될 수 있을 만큼 충분히 낮게 설정해야 한다.
2️⃣ replica.lag.time.max.ms (v2.5.0 default 10s → 30s)
리더로부터 데이터를 읽어 오거나, 리더에 쓰여진 최신 메시지를 따라잡아야 하는 최대 시간
- 컨슈머의 최대 지연에도 영향을 주게 되는데, 메시지가 모든 레플리카에 도착해서 컨슈머가 이 메시지를 읽을 수 있게 되는 데 최대 30s가 걸릴 수 있다.
디스크에 저장하기
카프카는 메시지를 받은 레플리카의 수에만 의존할 뿐, 디스크에 저장되지 않은 메시지에 대해서도 응답한다.
- 카프카는 세그먼트를 교체할 때(기본값: 1GB)와 재시작 직전에만 메시지를 디스크로 플러시한다.
- 그 외의 경우에는 리눅스의 페이지 캐시 기능에 의존하며, 페이지 캐시 공간이 다 찼을 경우에만 메시지를 디스크로 플러시한다.
각각 데이터의 복제본을 가지고 있는, 서로 다른 랙이나 가용 영역에 위치한 세 대의 장비가 리더의 디스크에 메시지를 쓰는 것보다 더 안전하다고 판단했다.
- 서로 다른 랙이나 가용 영역에서 동시에 장애가 발생할 가능성은 거의 없다.
브로커가 디스크에 더 자주 메시지를 저장하도록 설정할 수 있다.
- flush.messages: 디스크에 저장되지 않은 최대 메시지 수
- flush.ms: 얼마나 자주 디스크에 메시지를 저장할지
신뢰성 있는 시스템에서 프로듀서 사용하기
사용 가능한 높은 신뢰성 설정을 브로커에 적용했다면, 프로듀서 역시 신뢰성 있도록 설정하자
- 프로듀서 설정할 때 acks=1로 설정할 경우 메시지가 유실될 수 있다.
- 프로듀서가 에러를 처리하지 않고, 메시지 쓰기가 성공할 때까지 재시도하지 않으면 유실될 수 있다.
프로듀서 재시도 설정하기
프로듀서가 브로커에 메시지를 전송하면 브로커는 성공 혹은 두 부류의 에러코드를 리턴할 수 있다.
- 전송을 재시도하면 해결될 수 있는 것과 아닌 것이다.
- LEADER_NOT_AVAILABLE 경우 새로운 브로커가 리더로 선출되어 두 번째 시도는 성공할 수 있다.
- INVALID_CONFIG 경우 설정이 변경되지 않으면 재시도 하더라도 같은 예외를 리턴할 것이다.
재시도에 관한 가장 좋은 방법은 재시도 수를 기본값(MAX_INT, 사실상 무한)으로 두고 메시지 전송을 포기할 때까지 대기할 수 있는 시간을 지정하는 delivery.timeout.ms 설정값을 최대로 잡아주는 것이다.
- 이 시간 간격 내에 있는 한, 프로듀서는 메시지 전송을 계속해서 재시도한다.
전송 실패한 메시지를 재시도하는 것은 실패했다고 생각했지만 실제로는 성공하거나, 재전송된 메시지가 모두 브로커에 중복 저장될 위험을 내포한다.
- enable.idempotence=true 설정을 잡아서 프로듀서가 추가적인 정보를 레코드에 포함하여 브로커가 이를 활용해서 재시도로 인해 중복된 메시지를 건너뛸 수 있도록 할 수 있다.
추가적인 에러 처리
프로듀서에 탑재된 재시도 기능을 사용하면 메시지 유실 없이 다양한 종류의 에러를 쉽게 처리할 수 있지만, 개발자 입장에서는 다른 종류의 에러들 역시 처리할 수 있어야 한다.
- 메시지 크기에 관련되었거나, 인가 관련 에러와 같이 재시도가 불가능한 브로커 에러
- 직렬화 과정에서 발생한 에러처럼 메시지가 브로커에 전송되기 전에 발생한 에러
- 프로듀서가 모든 재전송 시도를 소진한 경우
- 재시도 과정에서 프로듀서가 사용하는 가용 메모리가 메시지로 가득 차서 발생하는 에러
- 타임아웃이 발생한 경우
메시지 재전송이 에러 핸들러가 하는 일의 전부라면, 프로듀서의 재전송 기능을 사용하는 편이 더 낫다.
신뢰성 있는 시스템에서 컨슈머 사용하기
컨슈머는 일관성을 보장하기 위해 모든 in-sync 레플리카에 쓰여진 다음부터 읽을 수 있으며, 메시지를 읽는 도중에 누락되지 않도록 메시지를 어디까지 읽었는지 추적해야 한다.
✅ 컨슈머가 메시지 누락 없이, 새로운 데이터를 올바른 순서로 읽을 수 있는 이유
파티션으로부터 데이터를 읽어올 때, 컨슈머는 메시지를 배치 단위로 읽어온 뒤 배치별로 마지막 오프셋을 확인하고 브로커로부터 받은 마지막 오프셋 값에서 시작하는 다른 메시지 배치를 요청한다.
✅ 컨슈머가 읽어온 오프셋을 커밋해야 하는 이유
읽고 있는 각 파티션에 대해 어디까지 읽었는지를 저장해 둬야 장애가 났었던 컨슈머나 다른 컨슈머가 재시작한 뒤에도 어디서부터 작업을 계속해야 할지 알 수 있다.
- 읽기는 했지만 아직 처리가 완료되지 않은 이벤트들의 오프셋을 커밋하면 메시지가 누락될 수 있다.
⚠️ 커밋된 메시지와 커밋된 오프셋
커밋된 메시지: 모든 in-sync 레플리카에 쓰여져서 컨슈머가 읽을 수 있는 메시지
커밋된 오프셋: 컨슈머가 특정 파티션에서 어느 오프셋까지의 모든 메시지를 받아서 처리를 완료했는지를 알리기 위해 카프카에 보낸 오프셋
신뢰성 있는 처리를 위해 중요한 컨슈머 설정
신뢰성을 갖는 컨슈머를 설정하기 위한 속성 4가지를 알아보자
- 속성 외에도 불필요한 리밸런싱과 리밸런싱이 발생했을 때의 멈춤을 최소화하기 위한 컨슈머를 설정해야 한다.
1️⃣ group.id
같은 그룹 ID를 갖는 컨슈머들이 같은 토픽을 구독할 경우 각각의 컨슈머에는 해당 토픽 전체 파티션의 서로 다른 부분집합이 할당되어 각각은 서로 다른 부분의 메시지만을 읽게된다.
- 컨슈머 그룹이 모든 메시지를 읽게 되며 컨슈머가 구독한 토픽의 모든 메시지를 읽기 위해서는 고유한 그룹 ID가 필요하다.
2️⃣ auto.offset.reset
커밋된 오프셋이 없을 때나 컨슈머가 브로커에 없는 오프셋을 요청할 경우 컨슈머가 어떻게 해야 할지를 결정한다.
- earliest를 사용하면 파티션의 맨 앞에서부터 읽기 시작하며, 많은 메시지들을 중복 처리하게 될 수 있지만 데이터 유실은 최소화 된다.
- latest를 사용하면 파티션의 끝에서부터 읽기를 시작해 중복 처리는 최소화하지만, 컨슈머가 일부 메시지는 누락된다.
3️⃣ enable.auto.commit
일정한 시간에 맞춰 컨슈머가 알아서 커밋하게 할 것인지, 코드에서 직접 오프셋을 커밋할지 정할 수 있다.
😎 장점
우리가 폴링 루프에서 읽어온 모든 레코드에 대한 처리를 하는 와중에 우리가 처리하지 않은 오프셋을 실수로 커밋하는 사태가 발생하지 않도록 보장해준다.
😭 단점
읽어온 메시지 중 일부만 처리했고 아직 자동 커밋이 되지 않은 상태에서 컨슈머가 멈추면, 컨슈머를 다시 시작시켰을 때 메시지 중복 처리를 피할 수 없다.
- 백그라운드에서 다른 스레드에 레코드를 넘기는 것처럼 복잡한 처리를 해야 할 경우 아직 처리하지는 않은 오프셋을 커밋할 수 있기 때문에 직접 오프셋을 커밋해주는 것 외에는 선택지가 없다.
4️⃣ auto.commit.interval.ms (default 5s)
자동으로 커밋되는 주기를 설정할 수 있는데, 더 자주 커밋할수록 오버헤드 역시 늘어나지만 컨슈머가 정지했을 때 발생할 수 있는 중복의 수는 줄어든다.
컨슈머에서 명시적으로 오프셋 커밋하기
1️⃣ 메시지 처리 먼저, 오프셋 커밋은 나중에
폴링 루프에서 모든 처리를 하고 루프 사이의 상태는 저장하지 않으면, 폴링 루프 끝에서 오프셋을 커밋하거나 루프 안에서 일정한 주기로 오프셋을 커밋함으로써 오버헤드와 중복 처리 회피 사이의 요구 조건의 균형을 맞추면 된다.
2️⃣ 커밋 빈도는 성능과 크래시 발생시 중복 개수 사이의 트레이드오프다.
루프 안에서 여러 번 커밋하거나 루프가 몇 번 지나갈 때마다 커밋하는 것 사이에서 선택할 수 있다.
- acks=all 설정에 쓰기 작업과 유사하게 커밋 작업은 상당한 성능 오버헤드를 수반한다.
- 특정 컨슈머 그룹의 모든 오프셋 커밋이 동일한 브로커로 가며 오버헤드가 발생한다.
커밋 주기는 성능과 중복 발생의 요구 조건 사이에서 균형을 맞춰야 한다.
- 메시지를 읽을 때마다 커밋하는 방식은 매우 낮은 빈도로 메시지가 들어오는 토픽에나 사용할 수 있다.
3️⃣ 정확한 시점에 정확한 오프셋을 커밋하자
읽기는 했지만 처리되지 않은 메시지의 오프셋을 커밋할 경우 컨슈머 입장에서는 메시지가 누락될 수 있다.
- 마지막으로 읽은 메시지의 오프셋이 아니라 마지막으로 처리된 메시지의 오프셋을 커밋하자
4️⃣ 리밸런스
컨슈머 리밸런스가 발생할 것이라는 것과 이것을 적절히 처리해줄 필요가 있다.
- 보통 할당된 파티션이 해제 되기 전에 오프셋을 커밋하고, 새로운 파티션이 할당되었을 때 애플리케이션이 보유하고 있던 상태가 있다면 삭제해주는 작업을 포함한다.
5️⃣ 컨슈머는 재시도 해야 할 수도 있다.
일부 레코드는 처리가 완료되지 않아서 나중에 처리되어야 할 수 있다.
- 전통적인 pub/sub 메시지 전달 시스템과는 달리, 카프카 컨슈머들은 오프셋을 커밋할 뿐 각각의 메시지에 응답을 보내지 않는다.
재시도 가능한 에러가 발생했을 때 사용할 수 있는 패턴
✅ 마지막으로 처리에 성공한 레코드의 오프셋을 커밋한다.
나중에 처리해야 할 레코드들은 버퍼에 저장하고 컨슈머의 pause() 메서드를 호출해서 추가적인 poll() 호출이 데이터를 리턴하지 않도록 한 뒤, 레코드 처리를 계속한다.
✅ 별도의 토픽에 쓴 뒤 계속 진행한다.
별도의 컨슈머 그룹을 사용해서 재시도 토픽에 저장된 레코드들을 처리하거나, 주 토픽과 재시도 토픽을 모두 구독하는 컨슈머를 하나둬서 재시도 사이에는 재시도 토픽 구독을 잠시 멈추도록할 수 있다.
- 많은 메시지 교환 시스템에서 사용되어 온 dead letter queue 시스템과 비슷하다.
6️⃣ 컨슈머가 상태를 유지해야 할 수도 있다.
만약 어떠한 평균값을 계산하고자 한다면, 카프카에서 새 메시지들을 폴링해 올 때마다 평균값을 업데이트 해야한다.
- 프로세스가 재시작될 때 마지막 오프셋에서부터 읽기 작업을 재개하고 평균값 역시 복구시켜야 한다.
마지막으로 누적된 값을 애플리케이션이 오프셋을 커밋할 때 results 토픽에 써서 스레드가 시작될 때, 작업이 중단된 시점과 마지막으로 누적된 값을 가져올 수 있다.
시스템 신뢰성 검증하기
프로덕션 환경에 시스템 신뢰성을 검증해야 한다.
다양한 시나리오를 고른 뒤 검증용 프로듀서와, 컨슈머를 실행해서 설정이 올바르게 적용되었는지 확인해봐야 한다.
- 아파치 카프카 소스코드 저장소는 방대한 테스트 스위트를 포함한다.
이후 애플리케이션 통합 테스트를 수행하여 다양한 장애 상황에 대해서 테스트를 수행해야 하며, 아파치 카프카는 장애 주입을 위한 자체적인 프레임워크인 Trogdor 테스트 프레임워크를 포함한다.
마지막으로는 프로덕션 환경에서 신뢰성을 모니터링 해야 한다.
카프카의 자바 클라이언트들은 클라이언트 쪽 상태와 이벤트를 모니터링할 수 있게 해주는 JMX 지표를 포함한다.
- 프로듀서의 경우 레코드별 에러율과 재시도율이 올라가는 것을 확인해야 한다.
이벤트 전송 도중에 발생하는 프로듀서 에러는 WARN, ERROR 레벨 로그 메시지들을 확인해야 한다.
- WARN 레벨에서 재시도 횟수가 0인 이벤트가 보인다면 재시도 횟수가 고갈된 것이다.
- ERROR 레벨은 재시도 불가능한 에러나, 재시도 횟수가 고갈된 재시도 가능한 에러나, 타임아웃으로 메시지 전송이 완전히 실패했음을 가리킬 가능성이 높으며, 이 경우 브로커로부터 리턴된 정확한 에러값 역시 함께 로그에 찍히게 된다.
컨슈머에서는 오픈소스 버로우처럼 컨슈머 랙을 모니터링 해야한다.
- 추가적으로 v0.10.0 부터 모든 메시지는 이벤트가 생성된 시점을 가리키는 타임스탬프를 포함한다.
- 타임스탬프는 이벤트를 전송중인 애플리케이션이나 관련 설정이 잡혀 있는 브로커에 의해 재정의 될 수 있다.
- 타임 스탬프를 활용한 프로듀서, 컨슈머 종단 모니터링 시스템도 필요할 수 있다.
카프카 브로커는 브로커가 클라이언트로 보내는 에러 응답률을 보여주는 지표들을 포함한다. (지표값을 수집하자)
- kafka.server:type=BrokerTopicMetrics, name=FailedProduceRequestsPerSec
- kafka.server:type=BrokerTopicMetrics, name=FailedFetchRequestsPerSec
'책 > 카프카 핵심 가이드' 카테고리의 다른 글
카프카 내부 메커니즘 (1) | 2024.12.22 |
---|---|
프로그램 내에서 코드로 카프카 관리하기 (2) | 2024.12.08 |
카프카 컨슈머 : 카프카에서 데이터 읽기 (1) | 2024.11.24 |
카프카 프로듀서: 카프카에 메시지 쓰기 (1) | 2024.11.09 |