이슈노트 #9: 이이제이
1. 발단
어느 날 갑자기 특정 시스템에 전방위적인 장애가 발생하기 시작했다.
갑자기 인증 토큰들이 유효하지 않다고 하면서 플랫폼에 대한 상호작용이 뻑난 것이다.
이 시스템은 다른 서드파티 플랫폼들을 중개하는 서비스였는데, 그렇기 때문에 각각의 플랫폼에 대한 인증 토큰을 등록해두고 갱신하면서 그걸 사용했다. 그 인증 토큰에 대한 갱신이 유효하게 동작하지 않았던 것이다.
2. 분석
좀 분석해보니 결과적으로는 스케줄러에서 문제가 생긴 것으로 파악이 됐다.
이 시스템은 RabbitMQ를 중심에 두고 그걸 통해서 이벤트를 전송, 주기적인 동작을 구성했었다.
예를 들면 1시간에 한번씩 스케줄러가 트리거되면서 MQ에 인증 토큰 갱신 이벤트를 전송하면, 메인 서버가 이벤트를 읽어다가 갱신 동작을 수행하는 식이었다.
아무튼 스케줄러 측 로그를 보니 다음과 같은 오류가 발생하면서 이벤트를 보내는 동작 자체가 막혀있었다.
.png?type=w800)
이건 그냥 RabbitMQ에서 채널이란 리소스가 부족할 때 발생하는 오류고, 실제로 채널의 누수가 발생하고 있었다.
그래서 일단은 빠르게 재부팅해서 누수를 임시로 해소하고, 며칠내로 적당히 수정해서 해결하려고 생각했다.
누수로 문제가 발생한 것도 최종 기능 배포 후 2주 정도 지난 뒤였고, 사용 패턴이나 트래픽도 큰 차이 없이 유지되었기에 며칠 정도는 버티리라 낙관했다.
근데 아니었다.
3. 당황
누수를 임시로 해소하고 나서 하루 정도 지나자마자 동일한 누수 문제가 금방 재발해 임계치에 도달했다.
그래서 일단 누수가 발생할 수 있는 부분을 수정해서 빠르게 핫픽스해서 해결했다.
사실 누수가 발견되고 나서 원인을 찾고 수정하는 것은 어려운 일이 아니었다. 그저 누수가 예상치 못한 속도로 발생한 것이 당황스러웠을 뿐이다. 일주일도 넘게 버티던 리소스 용량이 하루만에 찬다고?
심지어 누수가 발생한 코드포인트 자체는 들어간지 한달도 더 된 코드였다.
4. 반추
잠깐 않아서 과거를 되새겨보니 답이 나왔다.
문제가 발생하기 1-2일 전쯤에, 스케줄러가 주기적으로 다운되는 문제를 찾아서 해결한 적이 있었다.
그냥 이런 사소한 오류로 인해서 매일 새벽마다 한번씩 서버가 다운되고, 재실행됐었다.
스케줄러 특성상 서버 다운으로 인한 문제가 잘 드러나지 않고, 심지어 에러 리포팅도 구축되어있지 않아서 이런 문제가 발생하는 것 자체를 매우 늦게 알았다. 2-3달은 됐다.
그래서 다운되는건 좀 아니니, 예외처리만 추가해서 가볍게 핫픽스를 올렸는데... 성급한 버그 수정이 오히려 독이 된 것이다.
뭐냐면, 저 스케줄러 다운으로 인해서 스케줄러가 들고 있던 RabbitMQ 커넥션이 끊어지고, 그에 따른 채널도 끊기면서 너무 자연스럽게 누수가 해결되고 있었는데, 버그를 치우니까 가려져있던 치명적인 버그가 드러난 것이다.
스케줄러가 건강하게 잘 살아있으니 누수는 알차게 쌓여만 가고...
5. 정리
정리하자면,
- 누수로 인한 버그는 예전부터 있었으나,
- 주기적으로 스케줄러가 터지는 버그로 인해 누수가 숨겨졌고
- 스케줄러가 터지는 버그를 수정하니
- 누수가 빗발치면서 더 큰 버그를 유발한 것이다.
꽤 신선한 유형의 이슈라서 기록해본다.