프로듀서 기본 동작
프로듀서는 카프카의 토픽으로 메시지를 전송하는 역할을 담당한다.
프로듀서의 디자인은 아래 다이어그램과 같다.
ProducerRecord
는 카프카로 전송하기 위한 실제 데이터- topic, partition, key, value로 구성
- 카프카는 특정 토픽으로 값(메시지)을 전달하기 때문에 topic/value는 필수값.
- 특정 파티션을 지정하기 위한 레코드의 파티션과 정렬을 위한 키는 선택사항
- 레코드는 프로듀서의
send()
메서드를 통해serializer
->partitioner
를 거친다.- 프로듀서 레코드가 파티셔너를 지정했다면 파티셔너는 아무 동작도 하지 않고 지정된 파티셔너로 레코드를 전달함.
- 파티션을 지정하지 않은 경우 키를 가지고 파티션을 선택해 레코드를 전달한다.
- 이때 기본적으로 라운드 로빈(RR) 방식을 사용한다.
send()
를 호출하면 프로듀서 내부에서는 배치처리를 위해 레코드를 바로 전송하지 않고 파티션 별로 모아둔다.- 전송이 실패하면 지정된 횟수 만큼 재시도하고 최종 실패하면 예외, 성공하면 메타데이터를 리턴한다.
프로듀서가 메시지를 전송하는 세 가지 방식이 있음
- 메시지를 보내고 확인하지 않기
- 동기 전송
- 비동기 전송
컨슈머 기본 동작
- 컨슈머는 카프카 토픽에 저장되어 있는 메시지를 가져오는 역할이다.
- 프로듀서가 카프카 토픽으로 메시지를 전송하면 해당 메시지들은 브로커의 로컬디스크에 저장됨.
- 컨슈머는 토픽에 저장된 메시지를 가져온다.
- 컨슈머는 반드시 컨슈머 그룹에 속한다.
- 컨슈머 그룹은 하나 이상의 컨슈머가 모인 그룹.
- 파티션 수와 컨슈머 수는 1:1로 매핑되는 것이 일반적.
- 컨슈머 수가 파티션 수보다 많다고 해서 더 빠르게 토픽의 메시지를 가져오거나, 처리량이 높아지지 않음.
- 더 많은 수의 컨슈머들이 그냥 대기 상태로만 존재.
컨슈머가 브로커에서 메시지를 읽어오는 방식도 세 가지.
- 오토커밋
- 컨슈머 기본값으로 가장 많이 사용.
- 오토 커밋은 오프셋을 주기적으로 커밋해서 관리자가 관리하지 않아도 됨.
- 반면 컨슈머 종료 등이 빈번히 일어나면 일부 메시지를 못 가져오거나 중복 발생할 수 있음.
- 하지만 카프카가 안정적이어서 자주 씀.
- 동기
- 오토 커밋과 달리 poll로 가져온 후 현재 오프셋을 커밋함.
- 속도는 느리지만 메시지 손실은 거의 없음.
- 메시지 손실이란 실제로 토픽에는 메시지가 존재하지만 잘못된 오프셋 커밋으로 인한 위치 변경으로 컨슈머가 메시지를 가져오지 못하는 경우를 말함.
- 중요한 작업은 동기 방식을 권장.
- 비동기
- 동기와 차이점은 오프셋 커밋을 실패해도 재시도하지 않음.
- 이건 당연한데, 1번부터 100번 오프셋을 비동기로 가져온다고 생각해보자.
- (극단적인 예시) 1번부터 100번까지의 오프셋 중 2번 빼고 모두 성공했고 100번 오프셋을 커밋함.
- 2번 오프셋을 재시도하다가 성공해서 2번 오프셋을 커밋함.
- 그럼 컨슈머는 마지막 커밋이 2번 오프셋이니 3번부터 오프셋을 받아오려고 시도함.
- 중복 발생.
- 이런 이유로 비동기 방식은 재시도하지 않음.
컨슈머 그룹
- 컨슈머는 컨슈머 그룹 안에 속한 것이 일반적인 구조.
- 하나의 그룹 안에 여러 컨슈머가 구성될 수 있음.
- 토픽의 파티션과 일대일로 매핑되어 메시지를 가져옴.
- 그룹 내 컨슈머들은 서로의 정보를 공유함. 컨슈머01이 문제가 생겨 종료되면 컨슈머02 또는 컨슈머03은 컨슈머01이 컨슘하던 파티션을 대신 컨슘함.