

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Apache Kafka 클라이언트의 모범 사례
<a name="bestpractices-kafka-client"></a>

Apache Kafka 및 Amazon MSK에서 작업할 때는 최적의 성능과 신뢰성을 위해 클라이언트와 서버를 올바르게 구성하는 것이 중요합니다. 이 가이드에서는 Amazon MSK에 대한 모범 사례 클라이언트 측 구성에 대한 권장 사항을 제공합니다.

Amazon MSK Replicator 모범 사례에 대한 자세한 내용은 [MSK Replicator 사용 모범 사례](msk-replicator-best-practices.md) 단원을 참조하세요. Standard 및 Express 브로커 모범 사례는 [Standard 및 Express 브로커 모범 사례](bestpractices-intro.md) 섹션을 참조하세요.

**Topics**
+ [Apache Kafka 클라이언트 가용성](#bestpractices-kafka-client-client-availability)
+ [Apache Kafka 클라이언트 성능](#bestpractices-kafka-client-performance)
+ [Kafka 클라이언트 모니터링](#bestpractices-kafka-client-monitoring)

## Apache Kafka 클라이언트 가용성
<a name="bestpractices-kafka-client-client-availability"></a>

Apache Kafka와 같은 분산 시스템에서는 고가용성을 보장하는 것이 신뢰할 수 있고 내결함성 있는 메시징 인프라를 유지하는 데 매우 중요합니다. 브로커는 업그레이드, 패치 적용, 하드웨어 장애, 네트워크 문제 등와 같은 예정된 이벤트와 예정되지 않은 이벤트 모두에 대해 오프라인 상태가 됩니다. Kafka 클러스터는 오프라인 브로커 오류를 처리할 수 있으므로 Kafka 클라이언트도 브로커 장애 조치를 정상적으로 처리해야 합니다. Kafka 클라이언트의 고가용성을 보장하려면 다음 모범 사례를 사용하는 것이 좋습니다.

**생산자 가용성**
+ 브로커 장애 조치 중에 실패한 메시지 전송을 다시 시도하도록 생산자에게 지시하도록 `retries`를 설정합니다. 대부분의 사용 사례에는 최대 정수 값 또는 이와 유사한 높은 값을 사용하는 것이 좋습니다. 이렇게 하지 못하면 Kafka의 고가용성이 저하됩니다.
+ 메시지를 보내는 시간과 브로커로부터 확인을 받는 시간 사이의 총 시간에 대한 상한을 지정하도록 `delivery.timeout.ms`를 설정합니다. 이는 메시지가 유효한 기간의 비즈니스 요구 사항을 반영해야 합니다. 장애 조치 작업을 완료하는 데 충분한 재시도를 허용할 수 있도록 시간 제한을 충분히 높게 설정합니다. 대부분의 사용 사례에는 60초 이상의 값을 사용하는 것이 좋습니다.
+ 재전송을 시도하기 전에 단일 요청이 기다려야 하는 최대 값으로 `request.timeout.ms`를 설정합니다. 대부분의 사용 사례에는 10초 이상의 값을 사용하는 것이 좋습니다.
+ 재시도 급증 및 가용성 영향을 방지하기 위해 재시도 간의 지연을 구성하도록 `retry.backoff.ms`를 설정합니다. 대부분의 사용 사례에는 200ms의 최소값을 사용하는 것이 좋습니다.
+ 높은 내구성을 구성하도록 `acks=all`을 설정합니다. 이는 ISR의 모든 파티션이 쓰기를 승인하도록 하려면 `RF=3` 및 `min.isr=2`의 서버 측 구성과 일치해야 합니다. 단일 브로커 오프라인 중에 이는 `min.isr`, 즉 `2`입니다.

**소비자 가용성**
+ 새로운 소비자 그룹 또는 재생성된 소비자 그룹에 대해 `auto.offset.reset`을 처음에 `latest`로 설정합니다. 이렇게 하면 전체 주제를 소비하여 클러스터 부하가 추가될 위험을 피할 수 있습니다.
+ `enable.auto.commit`를 사용할 때 `auto.commit.interval.ms`를 설정합니다. 대부분의 사용 사례에서는 추가 로드 위험을 방지하기 위해 최소 5초의 값을 사용하는 것이 좋습니다.
+ 소비자의 메시지 처리 코드 내에서 예외 처리를 구현하여 회로 차단기 또는 지수 백오프가 있는 절전 모드와 같은 일시적인 오류를 처리합니다. 이렇게 하지 않으면 애플리케이션 충돌이 발생하여 과도한 재조정이 발생할 수 있습니다.
+ `isolation.level`을 설정하여 트랜잭션 메시지를 읽는 방법을 제어합니다.

  기본적으로 `read_uncommitted`를 항상 간결하게 설정하는 것이 좋습니다. 이는 일부 클라이언트 구현에서 누락됩니다.

  계층형 스토리지를 사용할 때는 `read_uncommitted`의 값을 사용하는 것이 좋습니다.
+ 가장 가까운 복제본 읽기를 사용하도록 `client.rack`을 설정합니다. 네트워크 트래픽 비용과 지연 시간을 최소화하도록 `az id `를 설정하는 것이 좋습니다. [랙 인식을 통해 Amazon MSK 소비자의 네트워크 트래픽 비용 절감](https://aws.amazon.com/blogs/big-data/reduce-network-traffic-costs-of-your-amazon-msk-consumers-with-rack-awareness/)을 참조하세요.

**소비자 재조정**
+ 구현된 시작 지터를 포함하여 애플리케이션의 시작 시간보다 큰 값으로 `session.timeout.ms`를 설정합니다. 대부분의 사용 사례에는 60초의 값을 사용하는 것이 좋습니다.
+ 그룹 조정자가 소비자를 정상으로 보는 방법을 미세 조정하도록 `heartbeat.interval.ms`를 설정합니다. 대부분의 사용 사례에는 10초의 값을 사용하는 것이 좋습니다.
+ 세션 제한 시간을 사용하여 소비자가 그룹을 떠날 때를 식별하는 대신 애플리케이션에서 종료 후크를 설정하여 SIGTERM에서 소비자를 확실하게 닫습니다. Kstream 애플리케이션은 `internal.leave.group.on.close`를 `true`의 값으로 설정할 수 있습니다.
+ 소비자 그룹 내에서 고유한 값으로 `group.instance.id`를 설정합니다. 이상적으로는 호스트 이름, task-id 또는 pod-id가 적합합니다. 문제 해결 중에 더 결정적인 동작과 더 나은 클라이언트/서버 로그 상관관계를 위해 항상 이 설정을 지정하는 것이 좋습니다.
+ `group.initial.rebalance.delay.ms`를 평균 배포 시간과 일치하는 값으로 설정합니다. 이렇게 하면 배포 중에 지속적인 재조정이 중지됩니다.
+ 고정 할당자를 사용하도록 `partition.assignment.strategy`를 설정합니다. `StickyAssignor` 또는 `CooperativeStickyAssignor`를 사용하는 것이 좋습니다.

## Apache Kafka 클라이언트 성능
<a name="bestpractices-kafka-client-performance"></a>

Kafka 클라이언트의 고성능을 보장하려면 다음 모범 사례를 사용하는 것이 좋습니다.

**생산자 성능**
+ 배치가 채워질 때까지 생산자가 기다리는 시간을 제어하도록 `linger.ms`를 설정합니다. 더 작은 배치는 한 번에 더 많은 스레드 및 I/O 작업으로 변환되므로 Kafka에 컴퓨팅 비용이 많이 듭니다. 다음 값을 사용하는 것이 좋습니다:

  지연 시간이 짧은 모든 사용 사례에 대한 최소값은 5밀리초입니다.

  대부분의 사용 사례에서는 25밀리초의 더 높은 값을 사용하는 것이 좋습니다.

  지연 시간이 짧은 사용 사례에서는 0의 값을 사용하지 않는 것이 좋습니다. (0의 값을 사용하면 일반적으로 IO 오버헤드로 인해 지연 시간이 발생합니다.)
+ 클러스터로 전송된 배치 크기를 제어하도록 `batch.size`를 설정합니다. 이 값을 64KB 또는 128KB의 값으로 늘리는 것이 좋습니다.
+ 더 큰 배치 크기를 사용할 때에는 `buffer.memory`를 설정합니다. 대부분의 사용 사례에는 64MB의 값을 사용하는 것이 좋습니다.
+ 바이트 수신에 사용되는 TCP 버퍼를 제어하도록 `send.buffer.bytes`를 설정합니다. 지연 시간이 긴 네트워크에서 생산자를 실행할 때 OS에서 이 버퍼를 관리하도록 하려면 -1 값을 사용하는 것이 좋습니다.
+ 배치의 압축을 제어하도록 compression.type을 설정합니다. 지연 시간이 긴 네트워크에서 생산자를 실행하는 lz4 또는 zstd를 사용하는 것이 좋습니다.

**소비자 성능**
+ 최소 가져오기 크기를 제어하여 가져오기 및 클러스터 부하 수를 유효하게 줄이도록 `fetch.min.bytes`를 설정합니다.

  모든 사용 사례에 대해 32바이트의 최소값을 사용하는 것이 좋습니다.

  대부분의 사용 사례에서는 128바이트의 더 높은 값을 사용하는 것이 좋습니다.
+ fetch.min.bytes가 무시되기 전까지 소비자가 대기하는 시간을 결정하도록 fetch.max.wait.ms를 설정합니다. 대부분의 사용 사례에서는 1,000밀리초의 값을 사용하는 것이 좋습니다.
+ 더 나은 병렬 처리와 복원력을 위해 컨슈머 수는 최소한 파티션 수와 같도록 지정하는 것이 좋습니다. 경우에 따라 처리량이 적은 토픽에 대해 파티션 수보다 적은 컨슈머를 선택할 수 있습니다.
+ 바이트 수신에 사용되는 TCP 버퍼를 제어하도록 `receive.buffer.bytes`를 설정합니다. 대기 시간이 긴 네트워크에서 소비자를 실행할 때 OS에서 이 버퍼를 관리하도록 하려면 -1 값을 사용하는 것이 좋습니다.

**클라이언트 연결**

연결 수명 주기에는 Kafka 클러스터에 대한 계산 및 메모리 비용이 발생합니다. 한 번에 너무 많은 연결이 생성되면 Kafka 클러스터의 가용성에 영향을 미칠 수 있는 부하가 발생합니다. 이러한 가용성 영향으로 인해 애플리케이션이 훨씬 더 많은 연결을 생성해서 캐스케이드 실패를 유발하여 완전 중단이 발생할 수 있습니다. 합리적인 속도로 생성하면 많은 수의 연결을 실현할 수 있습니다.

높은 연결 생성률을 관리하려면 다음과 같은 완화 조치를 사용하는 것이 좋습니다.
+ 애플리케이션 배포 메커니즘이 모든 생산자/소비자를 한 번에 다시 시작하지는 않지만 더 작은 배치로 시작하는 것이 좋습니다.
+ 애플리케이션 계층에서 개발자는 관리자 클라이언트, 생산자 클라이언트 또는 소비자 클라이언트를 생성하기 전에 무작위 지터(랜덤 절전 모드)가 수행되도록 해야 합니다.
+ SIGTERM에서 연결을 종료할 때 모든 Kafka 클라이언트의 연결이 동시에 종료되지 않도록 무작위 절전 모드를 실행해야 합니다. 무작위 절전 모드는 SIGKILL이 발생하기 전까지 제한 시간 내에 있어야 합니다.  
**Example 예제 A(Java)**  

  ```
  sleepInSeconds(randomNumberBetweenOneAndX);
                          this.kafkaProducer = new KafkaProducer<>(this.props);
  ```  
**Example 예제 B(Java)**  

  ```
  Runtime.getRuntime().addShutdownHook(new Thread(() -> {
      sleepInSeconds(randomNumberBetweenOneAndTwentyFive);
      kafkaProducer.close(Duration.ofSeconds(5));
  });
  ```
+ 애플리케이션 계층에서 개발자는 클라이언트가 싱글톤 패턴으로 애플리케이션당 한 번만 생성되도록 해야 합니다. 예를 들어 lambda를 사용하는 경우 메서드 핸들러 내에서가 아닌 전역 범위에서 클라이언트를 생성해야 합니다.
+ 안정적인 상태를 유지하기 위해 연결 수를 모니터링하는 것이 좋습니다. 배포 및 브로커 장애 조치 중 연결 생성/종료/교대는 정상입니다.

## Kafka 클라이언트 모니터링
<a name="bestpractices-kafka-client-monitoring"></a>

Kafka 클라이언트 모니터링은 Kafka 에코시스템의 상태와 효율성을 유지하는 데 매우 중요합니다. Kafka 관리자, 개발자 또는 운영 팀원이든 관계없이 클라이언트 측 지표를 활성화하면 예정된 이벤트와 예정되지 않은 이벤트 중에 비즈니스 영향을 이해하는 데 매우 중요합니다.

선호하는 지표 캡처 메커니즘을 사용하여 다음 클라이언트 측 지표를 모니터링하는 것이 좋습니다.

를 사용하여 지원 티켓을 신청할 때는 인시던트 중에 관찰된 모든 비정상적인 값을 AWS포함합니다. 또한 오류(경고 아님)를 자세히 설명하는 클라이언트 애플리케이션 로그 샘플도 포함하세요.

**생산자 지표**
+ byte-rate
+ record-send-rate
+ records-per-request-avg
+ acks-latency-avg
+ request-latency-avg
+ request-latency-max
+ record-error-rate
+ record-retry-rate
+ error-rate

**참고**  
참고: 리더 장애 조치 또는 네트워크 재전송과 같은 일시적 문제를 처리하기 위한 Kafka 프로토콜의 일부이므로 재시도 시 발생하는 일시적 오류는 우려할 사항이 아닙니다. `record-send-rate`는 프로듀서가 여전히 재시도를 진행하고 있는지 확인합니다.

**소비자 지표**
+ records-consumed-rate
+ bytes-consumed-rate
+ fetch-rate
+ records-lag-max
+ record-error-rate
+ fetch-error-rate
+ poll-rate
+ rebalance-latency-avg
+ commit-rate

**참고**  
가져오기 속도와 커밋 속도가 높으면 클러스터에 불필요한 부하가 발생합니다. 더 큰 배치로 요청을 수행하는 것이 가장 적합합니다.

**공통 지표**
+ connection-close-rate
+ connection-creation-rate
+ connection-count

**참고**  
연결 생성/종료가 많으면 클러스터에 불필요한 부하가 발생합니다.