high availability 서버를 만들기 어려운 이유

서비스에서 availability를 보장해주는 것은 매우 중요하다. three-nine(99.9%)의 availability를 보장하려면 일 년에 아홉 시간 이하의 다운타임만 있어야 하고, four-nine(99.99%)을 보장하려면 약 한 시간 이하, five-nine(99.999%)을 보장하려면 일 년에 다운 타임이 오 분 이하여야 한다.

보통 서버 장애는 서버가 가장 바쁠 때 발생하기 때문에 가능하면 다운 타임을 줄이는 것이 중요하지만, 현실적으로 이는 쉽지 않다. 상용 서비스 중에서도 three-nine 이상 보장하는 서비스를 찾기 힘들고, 어느 정도 이름 있는 서비스들은 돼야 four-nine, 정말 안정화가 잘 돼 있는 서비스들만이 five-nine 이상의 availability를 보장한다.

이는 high availability 서버를 만드는 것이 근본적으로 어려운 일이기 때문이다. 다운 타임이 적은 서버를 만들기 위해서는, 일단 버그가 없는 것은 기본이어야 한다. 하지만 서버 다운의 이유가 버그만 있는 게 아니다. 디스크나 네트워크 등 하드웨어 문제로 예상치 못하게 서버를 사용할 수 없게 되는 경우도 있다. 따라서 high availability 서버를 만들기 위해서는 문제가 생겼을 때 빠르게 재시작하는 것이 가장 중요한데 이를 위해서는 서버에 문제가 발생했을 때 이를 감시하고 있던 모니터가 빠르게 감지하여 서버에 문제가 발생하면 서버를 안전하게 죽이고, 새 서버를 띄워야 한다.

보통 서버에서 일정 시간 간격으로 메시지를 보내고 메시지가 오지 않으면 죽은 것으로 판단하는 heartbeat 방식을 많이 사용한다. 이때 heartbeat 자체는 보통 몇 초에 한 번 보내지만, 실제 서버가 죽지는 않았지만, 네트워크나 다른 문제로 메시지가 오지 않았을 것을 대비하여 몇 번의 메시지가 도착하지 않았을 때 서버가 죽었다고 판단한다. 즉, 실제로 서버에 문제가 발생해도 그를 감지하는 데만 적게는 십수초 많게는 몇십초의 시간이 걸린다.

그다음 문제는 서버를 빠르고 안전하게 죽이는 것이다. 보통은 프로그램이 죽는 것은 크게 신경 쓰지 않아도 된다. 프로그램이 죽으면 프로그램에서 사용하던 리소스는 OS가 알아서 처리해준다. 하지만 프로그램이 파일 시스템 등의 공유 자원을 사용하고 있었다면, 문제가 복잡해진다. 이 경우 수정한 공유자원을 원래대로 되돌리거나 처리하던 작업을 완료할 때까지 프로그램의 종료를 기다려야 한다.

마지막 문제는 서버를 빠르게 띄우는 것이다. 단순히 서버를 실행시키는 것은 시간이 오래 걸리지 않는다. 하지만 실행된 서버가 클라이언트의 요청을 정상적으로 처리할 수 있는 상태가 되는데 얼마나 걸릴지는 다른 문제다. 서버에서 사용해야 하는 다른 자원이 있으면 이 자원들을 초기화해야 하고, 서버에서 다른 서비스들을 이용하고 있다면 이 서비스들과의 접속도 다시 확인해야 한다. 게다가 하드웨어의 문제로 서버가 죽은 경우라면 기존에 사용하던 공유자원을 깔끔하게 정리하지 못하고 죽었을 것이기 때문에 이를 정리하는 일까지 해야 한다.

일반적으로 이상의 작업을 하면 서버에 문제가 발생하여 다시 시작하는 데까지 몇 분의 시간이 소모된다. 즉, 1년에 몇번의 장애만 발생해도 five-nine은 물론이고 four-nine조차 달성하기 어렵다.

댓글

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

RAII는 무엇인가

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API