Apache Flink 애플리케이션의 End-to-End Latency 병목 찾기
처리 시간과 처리 외 시간을 분리해 Flink latency 병목을 좁히는 방법.
end-to-end latency를 낮추려면 먼저 전체 Flink application을 operator 단위로 쪼개 관찰해야 한다. 이를 위해 각 operator에 두 종류의 histogram metric을 추가한다: 처리 시간은 map()이나 processElement()가 input을 처리해 output을 만드는 데 걸린 시간이고, 처리 외 시간은 그 밖의 모든 시간이다.
이렇게 나누면 병목의 성격이 바로 드러난다. 처리 시간이 크면 애플리케이션 로직, blocking I/O, Flink state 사용 패턴을 점검해야 하고, 처리 외 시간이 크면 네트워크 I/O나 Flink 내부 코드 실행을 의심할 수 있다. Flink 자체의 LatencyMarker도 존재하지만, 성능 저하가 크고 처리 시간/처리 외 시간을 분리해 볼 수 없으며, timer·aggregation·windowing이 있는 복잡한 job에서는 정확도도 떨어진다.
병목 operator를 찾은 뒤에는 operator flame graph로 더 깊게 파고든다. flame graph는 콜 스택을 샘플링해 함수별 실행 시간을 시각화하며, Flink web UI에서 확인할 수 있다. 다만 기본 비활성화 상태이므로 config.yaml에 rest.flamegraph.enabled: true를 설정해야 하고, 기본적으로 3분마다 샘플링이 이뤄져 해당 operator에 성능 저하가 발생한다. 그래서 실서버보다는 운영과 비슷한 부하의 테스트 환경에서 사용하는 것이 적절하다.
분석 결과는 크게 세 가지로 갈린다.
- 처리 시간이 병목이면 flame graph에서 유저 코드 구간이 대부분을 차지한다. 이때는 코드 레벨 inspection으로 느린 로직, blocking I/O, state backend 설정을 확인한다.
- 처리 외 시간 + 유저 코드 비중이 낮음이면 네트워크 I/O가 병목일 가능성이 높다.
taskmanager.network.*설정 튜닝과 네트워크 인프라 점검이 필요하다. - 처리 외 시간 + Flink 내부 코드 비중이 큼이면 serialization이나 state 처리 같은 내부 경로가 문제다. 예시로는 Kryo serializer가 병목이 된 경우가 있으며, runtime reflection 기반 Kryo 대신 더 빠른 POJO serializer가 쓰이도록 데이터 클래스를 바꾸는 식의 대응을 고려할 수 있다.
마지막으로 가장 중요한 점은, 이미 수집 중인 metric의 의미를 코드 레벨에서 다시 확인해야 한다는 것이다. 실제 사례에서도 처리 시간 metric만 있고 처리 외 시간 metric이 없어서 Kryo 병목을 놓쳤고, 기존 metric의 정의도 기대와 달라 시행착오가 컸다. 병목 진단의 출발점은 더 많은 metric이 아니라, 정확히 어떤 시간을 재고 있는지를 먼저 맞추는 데 있다.
이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.
요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.