Circuit Breaker는 장애 격리를 위해 사용이 되고 API 품질과 깊은 관련이 있습니다.
Circuit Breaker 라이브러리 중 하나인 Resilience4j에는 이번에 Slow Call 관련 설정을 할 수 있어 담당하고 있는 서비스에 Slow Call 관련 설정을 추가하는 것을 검토하였습니다.
예를 들어 200ms 이상 응답은 Slow Call로 간주하고 Slow Call이 전체 응답의 몇프로 이상일 때 Circuit Breadker를 OPEN 시키는 것입니다.
API 품질 = 사용자(클라이언트) 경험 품질
Slow Call 설정을 적용하기 전에 API 품질에 대해 먼저 고민해 볼 필요가 있습니다.
API 품질은 여러 측면에서 볼 수 있습니다. 응답 속도 측면에서 보면 빠를 수록 품질이 좋은 것이고, 가용성 측면에서 보면 서비스 불가능한 상태 최소화 또는 서비스 불가능할 때에도 적절하게 대처하는 것이 됩니다.
하지만 저는 사용자(클라이언트) 측면에서 보는 것이 적절하다는 견해를 가지고 있습니다.
왜냐하면 사용자 경험을 고려해야 적절한 목표도 세울 수 있고 사용자 경험을 고려하지 않은 단순한 응답 속도 개선, 가용성 개선은 별 의미가 없을 수 있기 때문입니다.
어떤 클라이언트를 가지고 있느냐에 따라 다르겠지만 일반적으로 웹/앱 서비스를 운영하는 입장에서는 F/E의 성능 지표를 우선 참고할 필요가 있습니다.
https://web.dev/i18n/ko/defining-core-web-vitals-thresholds/
Core Web Vitals 메트릭 및 임계값 정의
Core Web Vitals 임계값에 대한 연구 및 방법론
web.dev
여러 지표가 있지만 많은 경우 B/E와 직접적으로 관련이 있는 지표는 FCP, FID 라고 생각합니다.
물론 사진, 동영상 등 크기가 큰 컨텐츠를 제공하는 서비스의 경우 LCP도 중요한 지표가 될 수 있습니다.
FCP
화면에 컨텐츠가 처음 그려지는 시간이며 1.8초 이내에 들어오면 Good, 3초를 넘어가면 Poor 입니다.
First Contentful Paint(최초 콘텐츠풀 페인트, FCP)
이 게시물에서는 최초 콘텐츠풀 페인트(FCP) 메트릭을 소개하고 이를 측정하는 방법을 설명합니다.
web.dev
FID
그려진 컨텐츠와 상호작용했을 때 응답을 받는 시간이며 100ms 이내에 들어오면 Good, 300ms를 넘어가면 Poor 입니다.
First Input Delay(최초 입력 지연, FID)
이 게시물에서는 최초 입력 지연(FID) 메트릭을 소개하고 이를 측정하는 방법을 설명합니다.
web.dev
자바스크립트 동작, HTML, CSS 렌더링 등 여러 고려해야 할 것이 있지만
단순하게 요약하면 페이지 로딩과 관련되 API는 늦어도 1.8초 이내에, 액션과 관련된 API는 늦어도 100ms 이내에 응답해주는 것이 좋다고 할 수 있습니다.
Timeout
응답이 늦어질 때 아래 2가지 사이에서 균형을 맞추어야 합니다.
- 결과를 안보여주는 것보다 늦더라도 보여주는 것이 좋다.
- 계속 기다리게 하는 것보다는 빨리 다음 행동을 할 수 있게 해주는 것이 좋다.
기다려도 사용자가 기분이 나쁘지 않은 수준까지는 기다리고
사용자가 기다리다 기분이 나빠질 수 있을 정도가 되었을 때 즈음에는 대안을 마련해주는 것이 좋겠죠.
FCP 기준으로 말하면 3초까지는 기다려보고 3초에는 다음 행동을 할 수 있게 알려주는 것이 좋다는 것입니다.
클라이언트에서도 HTML, CSS 렌더링, Javascript 실행 등 작업이 있기 때문에 API 입장에서는 이것까지 고려해서 Timeout 시간을 고려해야 합니다.
예를 들어 F/E에서 FCP 관련 렌더링 하는데 1초 정도 걸릴 수 있다면 API는 최대 2초 안에 응답 되도록 할 수 있습니다.
2단계에 걸쳐 조회가 되고 각 단계마다 1번씩 Retry가 있다면 500ms 정도를 Timeout 수치로 설정해볼 수 있습니다.
Slow Call
Slow Call은 Timeout과는 약간 결이 다릅니다.
Timeout이 클라리언트 경험과 관련이 있었다면 Slow Call은 내부 서비스가 문제가 있는 경우에 사전에 요청을 차단해 내부 서비스 장애 상황을 방지하는데 목적이 있습니다.
내부 서비스가 느려지는 경우는 아래 2가지가 있습니다.
- 트래픽 증가했지만 스케일 아웃으로 감당 가능하며 자연스럽게 해소
- DB 병목 등 발생으로 지속적인 응답 지연 발생
위 2가지 중 첫번째 상황이 아닌 2번째 상황에서 Slow Call 관련 Circuit Breaker가 동작하도록 하는 것이 필요합니다.
어느 정도 느려졌을 뿐 충분히 응답 가능한 상황에서도 응답 실패 시켜 버리는 것은 옳지 못하기 때문입니다.
그래서 명확하게 지속적인 응답 지연 발생, 장애 상황인 경우에 동작할 수 있도록 해야 하며 저의 경우 P99 Latency가 50% 이상 발생할 때 서비스가 단순히 스케일 아웃만으로 해결이 안되는 상황으로 보았습니다.
추가로 Slow Call Ratio를 Failure Ratio와 동일하게 잡는 것도 큰 의미가 없습니다.
왜냐하면 대부분 Failure는 Timeout에 의해 발생하는 경우가 많기 때문입니다.
그래서 Slow Call Ratio를 50%로 잡았다면 Failure Ratio는 20~30% 정도로 잡는 것이 적절할 것으로 보입니다.
'제안&정리' 카테고리의 다른 글
[JAVA] enum find O(n) -> O(1) (0) | 2022.12.26 |
---|---|
[Git] Conventional Commit (0) | 2022.11.28 |
[React, React Native] Update 구독/발행 (0) | 2022.09.11 |
Latency 관리 (0) | 2022.08.21 |
[React Native] custom useAxios hook (0) | 2022.07.17 |