[Loki] Rate Batcher 도입으로 UpdateRates RPC 호출 대폭 감소
PR #20784 - feat: Introduce a rate batcher to batch rate updates
들어가며
Grafana Loki의 distributor에서 updateRates 요청이 매 push 요청마다 동기적으로 limits frontend에 전송되고 있었습니다. 이로 인해 RPC 호출 횟수가 O(D x P)/초(D: push 요청 수, P: 파티션 수)에 달하여 프론트엔드에 상당한 부하를 주고 있었습니다. 이 PR은 rateBatcher를 도입하여 rate 업데이트를 시간 윈도우 내에서 배치 처리합니다.
핵심 코드 분석
Before
func (t *DataObjTee) Duplicate(ctx context.Context, tenant string, streams []KeyedStream) {
// ...
rates, err := t.limitsClient.UpdateRates(ctx, tenant, segmentationKeyStreams)
if err != nil {
level.Error(t.logger).Log("msg", "failed to update rates", "err", err)
}
fastRates := make(map[uint64]uint64, len(rates))
for _, rate := range rates {
fastRates[rate.StreamHash] = rate.Rate
}
// ...
}
매 push마다 동기적으로 UpdateRates RPC를 호출합니다.
After
func (t *DataObjTee) Duplicate(ctx context.Context, tenant string, streams []KeyedStream) {
// ...
var fastRates map[uint64]uint64
if t.rateBatcher != nil {
// 배치 활성화: 배치에 추가하고 마지막 알려진 rate 반환
fastRates = t.rateBatcher.Add(tenant, segmentationKeyStreams)
} else {
// 배치 비활성화: 기존 동기 호출
fastRates = make(map[uint64]uint64, len(segmentationKeyStreams))
rates, err := t.limitsClient.UpdateRates(ctx, tenant, segmentationKeyStreams)
// ...
}
// ...
}
설정에서 rate_batch_window를 지정하면 rateBatcher가 활성화되어, 스트림 데이터를 시간 윈도우 동안 누적한 후 한 번에 UpdateRatesRaw로 전송합니다.
배치 윈도우 설정
distributor:
dataobj-tee:
rate_batch_window: 30s # 0이면 배치 비활성화
왜 이게 좋은가
- RPC 호출 극적 감소: O(D x P)/초에서 O(P)/30초로 변경되어, 수천 배의 RPC 호출 감소가 가능합니다.
- 비동기 배치 처리: push 경로에서 rate 업데이트 대기 시간이 사라져 push 지연이 줄어듭니다.
- 서비스 수명 주기 관리:
rateBatcher는 dskit의services.Service인터페이스를 구현하여, distributor의 서브서비스로 안전하게 관리됩니다. - 하위 호환성:
rate_batch_window: 0(기본값)이면 기존과 동일하게 동기 호출을 수행합니다.
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [Ultralytics] IMX 벤치마크에 세그멘테이션 모델 지원
- 현재글 : [Loki] Rate Batcher 도입으로 UpdateRates RPC 호출 대폭 감소
- 다음글 [Grafana Loki] batchDecoratorReader에서 읽기 에러 시 패닉을 방지하는 수정
댓글