목차
[개요]
- 카프카에서는 프로듀서 튜닝이 가장 핵심적인 요소이다.
- Throughput, latency는 프로듀서가 얼마나 효율적인 작업을 하는가에 따라 달라진다.
- Biz 요구사항을 가장 먼저 파악하고 그에 맞는 성능튜닝을 진행한다.
- Durability, Availability, Throughput, Latency 의 우선순위를 정해본다.
- 작은 변화를 위해 설정값을 변경하는 건 권고하지 않는다. 큰 변화일 때만 설정값을 변경한다. : https://www.confluent.co.uk/blog/configure-kafka-to-minimize-latency/
[Producer 내부 동작과정]
Producer의 튜닝을 하려면 내부동작도 잘 알아야 한다.
- Serializer : byte array 로 변환.
- Partitioner : 변환한 byte를 토픽의 어느 파티션으로 보낼 것인가를 결정.
- Record Accumulator : 메시지가 쌓이는 배치. 내부적인 Heap Memory를 사용한다.
- Compression : 압축, 브로커로 더 빠르게 전송 가능하나 압축하는 만큼의 cpu 사용률이 늘어날 수 있다.
- Sender Thread : sender request를 생성해 보냄.
[Producer Batch]
Producer에서 가장 중요한 것은 batch 처리이다. → 프로듀서 성능 개선의 중요한 포인트이다..!
배치 처리의 이점에 대한 Confluent 블로그. ( https://www.confluent.co.uk/blog/configure-kafka-to-minimize-latency/ )
- 배치 처리를 통해 네트워크 대역폭 사용을 감소시킬 수 있다.
- producer 에서 broker
- broker 에서 broker (replication)
- broker 에서 consumer
- 추가적인 이점
- 브로커 디스크의 스토리지 요구 사항 감소.
- 리퀘스트 감소로 인한 CPU 요구 사항 감소.
[성능 테스트 도구. Producer Perf Test]
- kafka에서는 Producer, Consumer를 위한 성능 테스트 도구를 제공한다.
- Producer용은 producer-perf-test이다.
- Apache Kafka 3.0미만까지는 RandomString이 적용되지 않아 압축을 테스트하는것이 적절하지 않았는데, 그 이후버전부터는 RandomString으로 메시지 내용이 생성되어 압축 테스트도 가능하다. (매번 같은 문자열일 경우 압축률이 일정하여 실사용과 차이가 크다)
다운로드
경로: https://kafka.apache.org/downloads
다운로드 후 압축을 풀고 bin 디렉토리에 스크립트 파일이 있다.
커맨드 예시
sudo ./kafka-producer-perf-test.sh \
--topic test-topic \
--num-records 1000 \
--record-size 100 \
--throughput 1000 \
--print-metrics \
--producer-props acks=-1 \
bootstrap.servers=localhost:9092 \
buffer.memory=67108864 batch.size=8196
- topic: 토픽명
- num-records: 전송할 메시지 수
- record-size: 메시지 크기
- throughput: TPS조절. -1로 할 경우 머신에서 낼 수 있는 최대 속도를 낸다. 위의 예시는 num-records가 1,000이고 throughput도 1,000이므로 1초만에 끝난다. TPS 1,000으로 1분간 지속하고 싶을 경우 throughput은 1,000으로 설정하고, num-records를 60,000으로 설정하면 된다.
- print-metrics: 상세한 메트릭 결과를 마지막에 노출
- producer-props: producer의 설정값들. 배치크기, acks 등등 조절하고 싶은 것들을 조절한다.
[성능 테스트 방법론]
접근 방법 ( Consumer 도 유사한 수준으로 진행 )
- kafka-producer-perf-test 를 사용한다.
- 기본값만으로 테스트를 먼저 한다.
- 메트릭 관찰
- 실행할 때마다 병목이 일어나는 포인트를 찾는다.
- 설정을 조정하고 다시 테스트하여 영향 측정한다.
- 반복..
즉, 기본값으로 테스트를 먼저 돌리고 거기에서 발생하는 병목 포인트를 찾아 점진적으로 개선해 나가는 방식으로 테스트하는 것이 좋다고 한다.
[성능 테스트 결과 해석하기]
주요 메트릭들
Metric | Meaning | MBean |
record-size-avg | 평균 레코드 크기 | kafka.producer:type=producer-metrics,client-id=([-.w]+) |
batch-size-avg | 평균 배치 크기 | kafka.producer:type=producer-metrics,client-id=([-.w]+) |
bufferpool-wait-ratio | Appender가 공간할당을 기다리는 시간의 비율 | kafka.producer:type=producer-metrics,client-id=([-.\w]+) |
compression-rate-avg | 압축율 (1이면 압축안됐다는 뜻. 낮을수록 압축률이 높음) | kafka.producer:type=producer-metrics,client-id=([-.w]+),topic=([-.w]+) |
record-queue-time-avg | 배치가 send 버퍼에서 머무른 시간 평균 (ms) | kafka.producer:type=producer-metrics,client-id=([-.w]+) |
request-latency-avg | 평균 request 지연 시간 (ms) | kafka.producer:type=producer-metrics,client-id=([-.w]+) |
produce-throttle-time-avg | 브로커에 의해 요청이 스로틀링 된 평균 시간 (ms) | kafka.producer:type=producer-metrics,client-id=([-.w]+) |
record-retry-rate | 토픽에 대해 전송을 다시 시도한 초당 평균 레코드 전송 횟수 | kafka.producer:type=producer-metrics,client-id=([-.w]+),topic=([-.w]+) |
- bufferpool-wail-ratio : buffer에 넣는데 걸리는 시간
- record-queue-time-avg : 실제로 레코들르 전송하는데 걸리는 시간
- 결과가 좋다면 데이터가 들어오자마자 브로커로 최대한 빨리 전송을 한다
- 해당 값을 개선시켜도 Linger.ms 를 준 경우 레코드가 계속 대기할 수 있다. = 처리시간이 늦어질 수 있다
- request-latency-avg : 브로커에서 ack를 받는데 걸리는 시간
- TPS를 늘렸을 때 지연시간 (request-latency-avg)이 늘어난다 → 클러스터가 문제, broker를 튜닝한다
- TPS를 늘렸을 때 지연시간은 많이 늘어나지 않는다 → 프로듀서 클라이언트가 문제
- request-size-avg : 브로커에 보낸 요청 크기
- batch-size-avg 와 유사하다면 batch 마다 reqeust 를 보낸다
- sender가 batch 를 쌓아서 보내지 않고 즉시 전송한다. (이미 Request가 다 찼으니깐 )
- linger.ms: batch 를 바로 보내지 않고 다른 Record들을 기다린다.
- 해당값을 늘려줘도 batch size가 다 찬다면 linger 값만큼 기다리지 않고 바로 전송한다.
- batch.size : request 로 보낼 record들을 얼마나 찼을때 보낼지 설정한다.
- batch-size-avg가 설정한 batch 보다 작다면 Linger 를 늘린다.
- max.in.flight.requests.per.connection 통해 request 한 번에 전송할 배치 수 결정. (기본값 5)
[예제 시나리오]
실제 예시는 아니고, 아래처럼 튜닝과정을 거친다고 가정한 시나리오이다.
먼저 100만 레코드를 보내도록 세팅하고, 기본 값으로 producer-perf-test를 수행한다.
1차 테스트. (기본값)
결과가 아래 처럼 나왔다고 가정하자.
bufferpool-wait-ratio = 0.666 (버퍼에 넣는데 60%의 시간을 썼다)
batch-size-avg = 16000 (배치를 항상 거의 꽉 채웠다)
compression-rate-avg = 1 (압축X)
record-queue-time-avg = 2391 (send버퍼에서 머무른 시간. 2391이라는건 2초이므로 여기서 지연이 많다)
request-size-avg = 21534 (배치가 쌓이는 대로 나갔다 정도로 이해)
=> 평균 지연시간이 높은편이다. 이 문제를 어떻게 해결할 수 있을까?
메트릭을 확인해보면 send 버퍼에서 머무른 시간이 주요 원인이다.Producer 큐에 넣는 것이 큐에서 나가는 것보다 많다는 뜻이며 이 말은 배치처리를 좀 더 개선할 필요가 있다는 뜻일 수도 있다.
배치 처리를 개선할 수 있는 요소들
- linger.ms = 배치를 채울 때 기다리는 시간 (기본값은 0이며 0일 경우 메시지가 올 때마다 가능한한 배치를 바로 전송해버린다)
- batch.size = 배치 크기 (기본값은 16384이며 꽉 차면 배치를 전송한다)
두 값에 의해 배치가 전송되며, linger.ms가 100이고 batch.size가 16384이면 배치가 꽉 차지 않더라도 100ms가 지난 후 배치를 전송하며 100ms안에 16384를 채우면 배치가 전송되기도 한다는 뜻이다.
만약 linger.ms를 기본값인 0으로 쓴다면 메시지가 올 때 마다 전송하게되어 배치를 효율적으로 활용하지 못하는 것이다.
이 시나리오에서는 이미 배치를 꽉 채우면서 보내고 있기 때문에 linger.ms를 늘려도 큰의미가 없다. 배치 크기를 늘려본다.
=> 16K -> 300K
2차 테스트. (배치 크기 증가 16K -> 300K)
결과가 아래처럼 나온다고 가정한다.
bufferpool-wait-ratio = 0.12
batch-size-avg = 250200 (300K를 채우지는 못했다)
...생략
기존 66%에서 12%로 줄었다. 하지만 배치를 꽉 채우지는 못했다.
linger.ms와 batch.size를 조합해서 테스트해볼 수 있다.
3차 테스트. (linger.ms = 100, batch.size = 300K)
결과가 아래처럼 나온다고 가정한다.
bufferpool-wait-ratio = 0.04
...
record-queue-time-avg = 1000 (많이 줄었다)
버퍼 관련값과 지연시간등이 많이 개선되었다.
하지만 아직 TPS를 -1로 주고있기 때문에 실사용과 맞지 않다.
실사용TPS값을 대략적으로 산정하여 테스트한다. 또한 압축도 해본다.
4차 테스트. (linger.ms =1000, batch.size=300K,TPS=1000, compression.type=lz4)
buffer-wait-ratio = 0.01 (더 이상 대기하지 않는다)
compression-rate-avg = 0.029 (2.90%면 매우 높은 압축률이다)
여기까지 하니 대부분의 수치가 개선되었고, producer에서는 더 이상 튜닝이 없는 것이라 판단한다.
[Client 성능지표]
클라이언트 성능지표를 통해 어느 포인트에서 병목이 발생하는지 짐작할 수 있다.
- io-wait-ratio: 이 값이 높다면 브로커에 문제가 있다고 판단할 수 있다. 즉, 브로커 튜닝 필요.
- io-ratio: io가 많이 발생한다.
- Producer: 메시지를 보내는 시간이 길다 -> producer의 batch size를 늘리거나 압축을 사용.
- Consumer: max.partition.fetch.size를 늘리거나 consumer group의 consumer를 추가 투입한다.
- 클라이언트 처리시간: 실제 브로커에서는 제대로 처리하고 있어서 클라이언트의 수정이 필요하다.
- Producer/Consumer의 로직 처리 시간이 너무 길지 않은지 확인한다.
'Kafka > Producer' 카테고리의 다른 글
Log Compaction (0) | 2023.03.05 |
---|---|
BuiltIn Partitioner (0) | 2023.03.05 |
Kafka Producer Basic Architecture (0) | 2023.03.03 |
Apache Kafka Client 2.4 이상 버전의 RoundRobin Partitioner에서 메시지가 골고루 분배되지 못하는 현상 (0) | 2022.12.03 |
Sticky Partitioner (0) | 2022.12.03 |