https://youtu.be/Hh9zcth4UcI?si=vCq-pKTm6xxopnDP
당근페이에서 발생했던 여러 문제들을 어떻게 해결했는지.
당근서비스와 함께 잘 성장하던 당근페이.
Redis에서 timeout 에러 발생 - redis 명령어 실행에 1500ms 이상 걸림.
Redis Java client인 Lettuce에서 확인해보니, 에러 발생 시점에 command명령어 지연이 발생함.
근데 Redis 서버에는 문제가 없음
JDBC에서 DB Connection 맺을 때도 timeout 발생. (8초 정도 걸림)
Deep Dive
마이페이지 상단에 '당근페이' 영역이 있다.
- 당근페이는 가입하지 않은 사용자에게도 송금이 가능함.
- 송금을 받았다면, '받지 않은 금액이 있다'는 정보를 표시해줌.
이걸 Traffic flow로 살펴보자면
- 당근페이 미가입 사용자의 '받지 않은 송금액 조회' HTTP 요청 -> Redis에 캐시된 정보 조회.
- Redis에 캐시된 게 없을 경우 DB 조회해서 가져온다.
당근페이 가입자의 경우에도 마찬가지. 호출하는 서비스는 다르지만 결국 Redis 조회 / Redis에 없을 경우 DB 조회하는 flow를 거친다.
에러 발생 시점: 서버에서 외부로 나가는 모든 outbound 통신이 실패함.
수많은 추정 원인 / Action Item
1. internal Service Segregation
microservice 분리.
- 기존에는 하나의 서버에서 모바일 앱, 웹 FE, 서버 간 요청을 전부 처리하고 있었음.
- 서버 리소스의 점유 비중에서 가장 큰 부분을 차지하는 하늘색, 핑크색, 노란색은 전부 서버 간 통신. 사용자의 직접적인 요청이 아니다.
- 이런 구조는 부하가 심한 상황에서 성능병목, 신뢰성 하락으로 이어질 수 있음
서버 간 통신을 담당하는 서비스를 별도로 분리 -> 사용자용 서버에 발생하는 부하를 낮췄음.
2. Event Streaming Pattern
원래는 서버에서 직접 Redis / Kafka 등의 리소스에도 접근.
- 결함을 예측하고 대처하는 시스템을 만들기 위해 apache flink기반 event streaming 구조 적용
- -> 웹 서버의 안정성 개선
3. ZGC 적용
- spiky traffic으로 DB에서 조회한 객체 로딩이 많아지면 GC가 자주 발생 -> Pause Time 증가.
- JVM heap 메모리 & GC time 최적화를 위해 ZGC 적용.
- ZGC 도입만으로도 GC time 최적화가 상당부분 이루어짐. JDK 21 쓰고있다면 도입 고려해도 좋을 거라 생각함
4. SQL Query Optimization
애플리케이션 메모리 사용 / DB부하 개선을 위한 Query Tuning
- 장표 사진은 AWS의 RDS Performance insight 이미지.
- 현재 DB 부하상태와, 부하에 영향을 주는 여러 쿼리를 보여준다. DBA 도움 없이도 개발자가 대응할 수 있음
예컨대 잔액조회를 위해 ORM에서 생성한 SQL query를 sum(count) 로 변경.
- 전체 송금 record 조회하는 방식 -> 전체 송금액 조회하는 방식.
- RPS가 높을 땐, 이런 query 최적화가 큰 개선이 됨.
5. API Performance Optimization
istio의 traffic topology 예시. 혹시 불필요한 서비스가 호출되지는 않는지 파악할 수 있음.
- 불필요한 api호출 정리한 결과 api latency가 15ms -> 3ms로 약 82% 감소
- DB QPS도 84%, CPU 사용량도 80% 감소.
6. Connection / Read Timeout 조정
- 외부요청을 보내기 전 Connection timeout
- 데이터 수신을 얼마나 기다릴 건지 결정하는 Read timeout.
너무 길면 불필요한 리소스 점유 + 사용자 경험에 안좋다.
TCP connection time 생각해서 connection timeout은 3초.
Read timeout의 경우 단순조회는 500ms 미만, 나머지는 컴포넌트 특성과 중요도에 따라 구분.
진짜 문제
당근은 microService 간 통신 제어를 위해 istio를 사용함.
- xDS 통해 서비스 호출을 위한 Endpoint 상태 전파.
- 배포 발생하면, 새로운 pod가 올라오므로 service discovery + 전파를 위해 push Metric이 급증.
istio는 application에 Sidecar 형태로 Envoy proxy를 주입하고, 애플리케이션으로 들고나는 트래픽을 관리함.
- envoy proxy의 Configuration 정보는 istiod에서 주입
- sidecar로 배포된 envoy proxy에 문제가 생기면, 애플리케이션 입장에서는 모든 네트워크 트래픽이 동작 안하는 것처럼 인식될 수 있음.
istio proxy에서 CPU Throttle이 발생.
- k8s 환경에서는 cpu limit을 걸어두면 cpu가 여유로운 상황에서도 throttle이 간혹 발생할 수 있다.
테스트 시작
CPU limit 때문에 Throttle이 발생했다.
- cpu 사용량이 높아서 throttle 발생 -> 네트워크 오류가 발생하는가?
- throttle 있는 상황에서 배포 진행 -> 네트워크 오류가 발생하는가?
- CPU limit 해제하면 처리 가능한 HTTP 요청이 증가하는가?
k6로 테스트 진행. 대시보드는 application, istio sidecar의 리소스 사용량.
테스트 결과, istio proxy의 cpu 사용량과 throttle 패턴이 동일함
HTTP latency도 증가함
해결
istio proxy에서 CPU limit 삭제하자, 문제 해결됨. 서비스 적용
다른 문제 발견
cpu 사용량이 지속적으로 늘어난다.
메모리 사용량도 계속 늘어난다.
느낀점
서비스의 load parameter (부하 파라미터): 시스템의 가용범위를 의미하는 수치.
- 웹서버의 RPS / DB의 read, write비율, cache hit 등...
- system metric이나 부하테스트로 관측 가능.
visibility 확보를 위해 "예측가능한 동작 보장"이 필요함.
- 당근페이는 코틀린, virtual thread 활용한 비동기 non-blocking 적극 활용중.
- 정상일 경우 / 부하일 경우의 상태파악이 중요함.
'학습일지 > Service Mesh' 카테고리의 다른 글
KubeCon2024 - Comparing Sidecar-Less Service Mesh from Cilium and Istio (0) | 2024.08.22 |
---|---|
Istio Memory 사용량 체크 - Knative Service 개수와 Sidecar Memory 관계 확인 (0) | 2023.10.09 |
istioCon 2022 - Egress Woes: Debugging External service Traffic in istio (0) | 2023.05.19 |
istioCon 2022 - Understanding New istio Telemetry API (0) | 2023.03.20 |
istioCon 2021 - What envoy hears when Istio Speaks (0) | 2023.02.03 |