Incident Library

IL-0452 Hyperconnect · 2024-06-24 (게시일)networking

한 나라의 한 통신사 3G IP 대역을 쓰는 Azar 사용자가 STOMP 로 통신하는 컴포넌트에 연결하지 못하고 read timed out 을 반복해서 겪었다

Hyperconnect 는 Azar 를 전 세계에 서비스한다. 2024년 1월 XY 국가의 극히 일부 사용자가 컴포넌트 A 와 관련된 오류를 겪는다는 CS 가 들어왔다. 그러나 컴포넌트 A 에는 변경이 없었고 서비스 지표도 크게 나빠지지 않아, 팀은 단서를 찾지 못한 채 넘어갔다. 그 뒤 관련 CS 가 12월 말부터 3월 셋째 주까지 선형적으로 늘었다는 리포트가 올라왔다. 기존 모니터링으로는 지역 네트워크의 일부에서만 생기는 문제를 추적할 수 없었다. 원인을 못 찾으면 그 나라로 출장까지 고려해야 할 상황이었다.

SRE 팀은 CS 시트와 Databricks 의 클라이언트 에러 로그를 분석해, 신고가 모두 통신사 Z 에서 왔고 Android 의 read timed out 이 점점 늘고 있다는 것을 알아냈다. 이 오류는 컴포넌트 A 와의 STOMP 커넥션이 시간 안에 맺어지지 않을 때 난다. 이 오류를 10번 넘게 겪은 사용자는 900명이 넘었다. Global Accelerator 로 지역 ISP 에서 AWS 까지의 경로를 바꿔도 변화가 없어 문제를 지역 네트워크 안으로 좁혔다. 기존 연결성 모니터링 솔루션으로는 모바일 환경에서 STOMP 를 시험할 수 없었다. 그래서 팀은 나라별 모바일 기기를 SOCKS5 프록시로 쓰게 해 주는 Oxylabs 를 썼다. 재현해 보니 통신사 Z 의 3G IP pool 에 붙은 기기에서만 응답이 오기까지 40초에서 2분이 걸려 timeout 이 났다.

재현이 되는 SRE 팀의 코드와 재현이 안 되던 다른 코드를 비교하니, TLS Client Hello 에 SNI 를 넣는지만 달랐다. STOMP 통신에 쓰던 라이브러리는 기본으로 SNI 를 넣지 않았다. 팀은 통신사 Z 가 SNI 유무에 따라 QoS pool 을 조절하는 설정을 조금씩 rolling update 로 적용하면서 오류가 늘었다고 추정했다. Android 팀과 iOS 팀이 SNI 를 넣는 핫픽스를 만들었다. 두 팀은 tun2socks 와 ShadowRocket 으로 SOCKS 프록시를 거쳐 동작 차이를 확인한 뒤 핫픽스를 배포했다. iOS 에서 오류 패턴이 보이지 않았던 것은 timeout 오류를 리포팅하는 로직의 버그 때문이었고, 이 버그도 같은 핫픽스에서 고쳤다. 새 버전을 쓰는 사용자가 늘면서 오류가 점점 줄었고 관련 CS 는 더 들어오지 않았다.

심각도
–
영향 범위
Azar users on carrier Z's 3G IP pool in country XY could not connect to component A over STOMP and got read timed out errors, many of them repeatedly
영향 사용자
As of 2024-03-26: 1,322 users with one error, 1,471 with 2 to 10, 798 with 10 to 100 and 147 with more than 100
지역
One country, called XY in the write-up
감지까지
–
복구까지
–

증상

2024년 1월 내부 CS 논의 채널에 XY 국가의 극히 일부 사용자가 Azar 에서 컴포넌트 A 와 관련된 오류를 겪는다는 제보가 들어왔다. 클라이언트에서는 몇 가지 에러 메시지가 꽤 많이 나고 있었다. 그러나 그 무렵 컴포넌트 A 에는 바뀐 것이 없었고 서비스 지표도 눈에 띄게 나빠지지 않았다.

관련 CS 는 12월 말부터 3월 셋째 주까지 선형적으로 늘었다. CS 를 모은 시트에서 통신사 정보가 있는 신고는 모두 통신사 Z 를 가리켰고, 안드로이드와 iOS 의 차이는 크게 보이지 않았다.

Databricks 로 클라이언트 에러 로그를 보니 하루 1,000회가 넘는 에러 타입 약 20개 중 점점 늘어나는 것은 Android 의 read timed out 하나였다. Android 팀은 이 오류가 컴포넌트 A 와의 커넥션이 시간 안에 맺어지지 않을 때 나는 것이라고 확인했다. 통신사 Z 로 걸러 보니 같은 증가 추이가 그대로 나타났다.

같은 사용자가 같은 오류를 반복해서 겪었다. 2024년 3월 26일 기준으로 오류를 1번 겪은 사용자는 1,322명, 2~10번은 1,471명, 10~100번은 798명, 100번 넘게 겪은 사용자는 147명이었다. timeout 은 모든 통신에서 나지 않고 컴포넌트 A 와의 STOMP 통신에서만 났다.

SRE 팀은 컴포넌트 A 가 모든 나라의 트래픽을 받고 있으므로 애플리케이션 문제는 아니라고 보았다. 현상이 오래 이어졌으므로 AWS 장애도 아니라고 판단했다. Global Accelerator 로 지역 네트워크에서 바로 AWS 회선으로 들어오게 경로를 바꿨지만 에러 추이는 변하지 않았다. 그래서 문제를 지역 네트워크 안으로 좁혔다.

팀은 Oxylabs 의 모바일 SOCKS5 프록시와 golang 으로 짠 STOMP 테스트 스크립트로 현상을 재현했다. 통신사 Z 의 3G IP pool 에 해당하는 특정 IP 대역에 붙은 기기에서만 응답이 오기까지 40초에서 2분이 걸렸다. 클라이언트의 timeout 은 이보다 훨씬 짧아서 요청은 모두 timeout 으로 끝났다. 한 번 연결이 안 된 사용자는 다시 요청해도 계속 느렸다. 같은 사용자라도 curl 로 HTTP 프록시를 거쳐 요청하면 응답이 금방 돌아왔다.

증상 간헐적 타임아웃

원인

촉발
STOMP 통신에 쓰던 라이브러리는 기본 설정에서 TLS Client Hello 에 SNI 를 넣지 않았다. SRE 팀은 통신사 Z 가 SNI 유무에 따라 QoS pool 을 조절하는 설정을 조금씩 rolling update 로 적용하면서 오류가 늘었다고 추정했다.

감지

XY 국가의 일부 사용자가 보낸 CS 가 내부 CS 논의 채널로 들어오면서 알게 됐다. 처음에는 원인을 못 찾고 넘어갔고, 관련 CS 가 계속 늘어난다는 리포트가 올라온 뒤에야 본격적으로 조사했다.

조치

후속 조치

교훈

SRE 팀은 회고에서, 첫 문제가 생기고 최소 3개월이 지나 CS 가 쌓인 뒤에야 문제를 보기 시작했다는 점을 짚었다. 글로벌 서비스에서는 예상하지 못한 지역 네트워크의 변화 때문에 일부 사용자가 회사 인프라에 제대로 연결하지 못할 수 있다. 팀은 이 문제를 다음 순서로 풀었다. 데이터 분석으로 볼 곳을 정하고, 문제 구간을 좁혀 모바일 프록시로 재현하고, 원인을 찾아 테스트한 뒤 핫픽스를 배포했다.

출처

참고 문서

관련 사례

–

내 클러스터에도 있는지 확인하기

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: ISP·트랜짓 망. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.