본문으로 건너뛰기

13. 다중성 확보, 시스템 안정화

33강. 다중성 확보

다중성 확보 - AP 서버

다중화에 대한 실제적인 이야기를 하자면 AP 서버에서는 확장성을 생각하는 방식과 마찬가지로 서버 여러 대를 늘어놓는 게 기본이 됩니다. 서버를 늘어놓을 때 중요한 것은 1대나 2대 정도 정지하더라도 충분히 처리할 수 있도록 처리능력을 확보해두는 것입니다.

서버는 다양한 요인으로 멈춥니다. 예를 들면 엔지니어가 서버 프로세스를 중지한 채로 잊어버리는 것과 같이 인위적인 실수에서부터 서버가 물리적으로 고장 났다거나 메모리에 이상이 생겨 멈춘다거나 다양한 상황이 있습니다.

이에 대한 대응으로 로드밸런서로 페일오버(failover, 장애극복)·페일백(fallback, 정상복귀)하여 고장 난 서버를 자동적으로 분리하고, 서버가 복구되면 원상태로 복귀시키는 작업을 수행하고 있습니다. 페일오버는 자동으로 분리하는 것, 페일백은 정상이 되면 복귀시키는 처리를 말합니다. 로드밸런서는 서버에 대해 주기적으로 헬스체크를 하고 있으며, AP 서버나 DB 서버가 살아있는지 여부를 판정하고 있습니다. 이는 다중화에서 가장 기본적인 부분입니다.

다중성 확보 - DB 서버

DB 서버도 마찬가지로 서버를 여러 대 나열해서 1, 2대 정지하더라도 충분한 처리능력이 있도록 해두는 것이 중요합니다. 또한 마스터의 다중화도 수행하고 있습니다. 5장에서는 마스터의 다중화가 어렵다는 이야기를 했었습니다. 그렇다면 하테나에서는 어떻게 다중화하고 있을까요? 바로 멀티 마스터라는 방법을 사용하고 있습니다.

멀티 마스터는 구체적으로 말하면 쌍방으로 레플리케이션, 즉 서로가 서로의 슬레이브가 되는 상태로 해두고, 한쪽에 쓰기작업을 하면 다른 한쪽으로 전달하고 반대쪽에 쓰더라도 다른 쪽으로 전달하는 양방향 레플리케이션 방법입니다. 다만 MySQL은 실제로 한쪽에 쓰기작업을 하면 반대쪽으로 전달되는 흐름이기 때문에 약간이나마 지연이 있습니다.

멀티 마스터

멀티 마스터는 최근 수년 내 MySQL 서버 구축에 있어 주류가 되었고, 여러 부분에 실적도 있는 숙련된 방법이 되었습니다. 페일오버에 대해 구체적인 동작을 설명하면, 상호간에 VRRP(Virtual Router Redundancy Protocol)라는 프로토콜로 감시를 하고 있습니다. VRRP에 의해 한쪽이 분리된 것을 알게 되면 자신이 Active 마스터로 승격합니다.

그림 13.3

멀티 마스터 구성에서 서버는 기본적으로 2대가 있으며, Active/Standby 구성을 하고 있습니다. Active/Standby 구성이라는 것은 한쪽은 Active이고 다른 한쪽은 Standby가 되어 기본적으로 항상 Active 쪽만 쓰기작업을 하는 구성입니다. Active인 서버가 다운되면 Standby였던 쪽이 Active로 승격해서 새로운 마스터가 되고, 다운된 서버는 수작업으로 복구시켜서 다시 Standby로 되돌리던가 다시 원래의 Active/Standby 구성으로 되돌립니다.

다중성 확보 - 스토리지 서버

스토리지 서버에 대해 알아보겠습니다. 하테나에서는 이미지 파일과 같은 미디어 파일을 저장하기 위한 분산 스토리지 서버로 MogileFS를 사용하고 있습니다. 분산 파일시스템을 사용함으로써 대량의 파일을 보존할 수 있는 확장성과 일부 서버가 다운되더라도 전체 장애가 되지 않도록 다중성을 확보할 수 있습니다.

분산 파일시스템은 깊이 있는 분야라서 지금도 인기가 있는 분야라고 생각합니다. 특정 노드가 다운되었을 때 해당 노드가 가지고 있는 데이터를 어떻게 해서 이동시킬 것인지, 특정 노드 상의 파일로 액세스가 편중될 때 이를 평준화하기 위해 데이터를 어떻게 재배치할 것인지 등 이와 관련된 여러 기술들이 있습니다.

34강. 시스템 안정화

시스템 안정화를 위한 상반관계

지금까지 시스템을 안정화시키기 위해 다중성을 확보하고 있다는 이야기를 해왔는데, 그 밖에도 다양한 대책을 마련하고 있습니다. 시스템을 안정화시키기 위해 상반되는 부분이 몇 가지 있는데, 우선 안정성과 자원효율 간에는 상반관계가 있습니다. 또한 안정성과 속도도 상반관계가 있습니다.

시스템의 불안정 요인

불안정 요인은 그야말로 시스템 구성이 복잡해지면 질수록 하늘의 별만큼 늘어나게 됩니다. 전형적인 요인만 아래에 나열해보았습니다.

  • 애플리케이션/서비스 레벨 -> 부하 증가
    • ❶ 기능 추가
    • ❷ 메모리 누수
    • ❸ 지뢰
    • ❹ 사용자의 액세스 패턴
    • ❺ 데이터량 증가
    • ❻ 외부연계 추가
  • 하드웨어 -> 처리능력 저하
    • ❼ 메모리, HDD(Hard Disk Drive) 장애
    • ❽ NIC(Network Interface Card) 장애

❶ 기능 추가, ❷ 메모리 누수

애플리케이션, 서비스 레벨에서 기능 추가는 물론 시스템의 불안정 요인입니다. 새로운 기능을 추가하면 그 기능이 예상보다 무거워서 전체적인 부하가 늘어나 서비스가 다운되는 일은 과거에 여러 번 있었습니다.

메모리 누수도 상당히 불안정한 요인입니다. 특히 Perl과 같은 Lightweight Language를 사용하다 보면 메모리 누수를 완전히 배제하기가 어려워서 아무리 해도 메모리가 조금씩 누수되어 가는데, 버퍼가 너무 작으면 시간이 지남에 따라 버퍼를 다 사용해서 스왑을 사용하기 시작해서 부하가 증가해가는 것을 알 수 있습니다.

❸ 지뢰

지뢰라는 항목이 있는데, 이것은 특정 URL이 읽히면(지뢰를 밟으면) 아무리 시간이 지나도 응답이 오지 않아서 마치 지뢰처럼 장애의 원인이 되는 현상을 말합니다. 그 원인으로는 메모리 누수나 무한루프 등 다양한 요인이 있습니다.

이 지뢰의 원인을 찾는 것은 상당히 어려운 일입니다. 왜냐하면 애플리케이션이 작동하고 있는데 지뢰를 밟으면 갑자기 시스템이 무거워지면서 다운되어버리기 때문입니다. 따라서 지뢰를 밟은 직후에 시스템이 다운되기 전에 찾아내지 못하면 어디에서 무엇이 지뢰가 되고 있는지 파악하기가 어려워집니다.

❹ 사용자의 액세스 패턴

사용자의 액세스 패턴 변화도 부하가 증대되는 원인이 됩니다. 예전에는 종종 Slashdot 효과나 Digg 효과라고 하곤 했는데, 인기가 많은 사이트에 링크를 걸어두면 그 사이트 사용자가 집중적으로 접속해서 다운되는 경우가 자주 있었습니다.

예를 들면 하테나에서는 yahoo! 어택이라고 불렀는데, Yahoo! 토픽스에 하테나 다이어리의 키워드가 링크되거나 특정 다이어리의 엔트리가 링크되어 보통일 때와 비교해서 차원이 다른 접속이 들어와서 다운되는 일이 과거에 여러 번 있었습니다. 전형적으로는 Squid와 같은 캐시 서버를 사이에 추가해서 게스트 사용자의 경우는 캐시를 반환할 수 있도록 해두는 방법이 있습니다.

❺ 데이터량 증가

데이터량 증가도 커다란 불안정 요인 중 하나입니다. 1년 정도 서비스가 안정적으로 운영되고 있더라도 머지 않아 당초 예상했던 데이터량보다도 늘어나서 이것이 전체적인 부하의 증가로 이어져서 시스템이 불안정해지는 경우가 있습니다.

예를 들면 얼마 전에 곤란한 일이 있었는데, 하테나 스타에 데이터량이 예상 외로 증가했던 적이 있습니다. 지금까지 수십 개 정도만 달았던 것을 아이들이 별을 100, 1,000개씩이나 달기 시작했던 것입니다. 우고메모를 시작하기 전에는 전체 별의 수가 수천만 정도였었는데, 우고메모를 릴리즈하고 잠시 지나서 수억대로 폭증했습니다.

당초 설계했을 때에는 예상하지 못했던 사용법으로 해서 비정상적으로 데이터량이 늘어나면 시스템이 불안정해지는 일이 자주 발생합니다. 이럴 때에는 DB 설계를 변경해서 이전에는 별 1,000개를 달면 1,000개의 레코드를 추가했었지만, 설계를 바꿔 1,000개를 추가했다는 정보를 가진 레코드를 1개만 추가하도록 해서 대처하면서 전체적인 레코드 수의 증가를 억제해 데이터량의 규모를 적정한 수준으로 줄이는 대책을 취했습니다.

❻ 외부연계 추가

외부연계 추가라는 것은 광고 관련 웹 API나 Amazon 웹 API 등을 새롭게 추가하는 등 외부의 새로운 웹 API를 연결하는 것을 말합니다.

이와 같은 외부연계를 늘리게 되면 외부시스템이 다운되어 있을 때 덩달아서 다운되는 형태가 되기 쉬우므로, 외부시스템이 다운되거나 다운되지는 않더라도 부하가 높을 때에도 연계하고 있는 서비스가 영향을 받지 않고 충분한 속도로 동작하거나 외부로부터 데이터를 가져올 수는 없지만 그 부분만 작동을 안 하고 다른 부분은 출력할 수 있도록 하는 등, 이러한 외부 노이즈에 견딜 수 있는 시스템을 구현하는 것도 중요합니다.

❼ 메모리, HDD 장애, ❽ NIC 장애

끝으로 하드웨어에 대해 살펴보겠습니다. 애플리케이션 엔지니어를 대상으로 한 강의이므로 여기서는 상세히 다루지 않겠지만, 메모리나 HDD, 네트워크 장애는 일상적으로 발생합니다. 따라서 하드웨어의 능력이 저하되더라도 문제가 되지 않도록 해두는 것도 중요합니다.

예를 들면 로드밸런서에서 적절한 항목에 대해 헬스체크를 해서 하드웨어 장애로 이상이 생겼을 때 바로 문제가 발생한 서버로 요청이 전송되지 않도록 할 수가 있습니다.

35강. 시스템 안정화 대책

실제 안정화 대책

안정화를 위한 사고방식에 대해 지금까지 언급해왔습니다. 실제 대책을 취하고 있는 방식은 크게 두 가지로, 적절한 버퍼 유지와 불안정 요인의 제거가 그것입니다.

먼저 적절한 버퍼 유지를 위해 한계의 7할 운용을 수행하고 있습니다. 시스템 수용능력의 70%를 상한선으로 해서 이를 넘어서면 서버를 추가하거나 메모리를 늘리는 등 임계치를 설정하는 방식을 취하고 있습니다.

불안정 요인을 제거하는 것과 관련해서는 SQL 부하대책, 메모리 누수 줄이기, 비정상동작 시 자율제어를 들 수 있습니다.

이상 동작 시의 자율 제어

이상 동작 시의 자율제어 대책으로 현재 ❶ 자동 DoS 판정, ❷ 자동 재시작, ❸ 자동 쿼리제거라는 세 가지 대책을 수행하고 있습니다.

첫 번째는 ❶ 자동 DoS 판정입니다. 이에 대한 대처방안으로 자동 DoS 판정을 수행하도록 해서 1시간에 특정 IP주소로부터 다수의 요청이 오면, 당분간 403을 반환해서 액세스를 자율적으로 차단함으로써 이와 같은 비정상 액세스에 대처하고 있습니다.

다음으로 ❷ 자동 재시작(AP 서버·호스트 OS)과 같은 구조도 마련되어 있습니다. 어느 정도 리소스를 지나치게 사용했다고 판단했다면 웹 서버를 재시작합니다. 또한 가상화되어 있는 호스트에서는 가상화되어 있는 OS별로 재시작을 하고 있습니다.

❸ 자동 쿼리제거(소요시간이 긴 SQL을 KILL)도 수행하고 있습니다. 자동 쿼리처리란 DB 서버에 어떤 쿼리가 실행되고 있는지를 10초에 한 번씩 파악해서 어느 정도 이상으로 시간이 경과한 쿼리를 강제적으로 KILL하는 것으로, 일부 서비스에서 테스트 중에 있습니다.

소요시간이 긴 SQL을 실행하면 DB가 멈춰버리는 경우가 종종 있는데, 어떤 액세스를 할 때 그런 SQL이 실행되는 것인지를 판명해서 문제를 해결해야 합니다. 이를 위해서는 코드를 수정해야 할 필요가 생기므로 곧바로 개선하기에는 어려움이 많습니다. 잠정적인 조치의 의미를 포함해서 자동 쿼리제거를 일부 서비스에서 수행하고 있는 상황입니다.

다만 이러한 자율제어가 지나치게 잘 작동하게 되면 문제를 방치해두더라도 시스템이 안정적으로 운용되어 애플리케이션을 적당히 만들어도 그런대로 동작하게 됩니다. 자율제어는 잠정적인 해법이고 본질적인 해법이 아니라는 것을 염두에 두고 코드를 작성하는 것이 중요합니다.

Wrap Up

대규모 시스템의 안정화는 서버를 여러 대 두는 다중성 확보만으로 끝나지 않고, 장애 원인을 빠르게 분리하고 비정상 동작을 완화하는 운영 장치까지 함께 갖추는 과정입니다. 특히 Active/Standby 기반 멀티 마스터, 분산 스토리지, 70% 상한 운용, 자율제어 같은 방식은 장애를 견디기 위한 현실적인 대책이지만, 어디까지나 본질적인 코드 개선과 함께 가야 합니다.

Summary

AP 서버는 여러 대를 두고 로드밸런서의 헬스체크와 페일오버·페일백으로 기본적인 다중화를 구성할 수 있습니다. DB 서버는 더 어렵지만, 하테나에서는 양방향 레플리케이션 기반 멀티 마스터와 Active/Standby 구성을 통해 마스터 장애에 대응하고 있습니다. 스토리지 서버는 MogileFS 같은 분산 파일시스템을 사용해 파일 저장의 확장성과 다중성을 함께 확보합니다. 한편 시스템 불안정 요인은 기능 추가, 메모리 누수, 지뢰 URL, 액세스 패턴 변화, 데이터량 증가, 외부연계, 하드웨어 장애처럼 매우 다양하므로 이를 전제로 한 운영이 필요합니다. 그래서 실제 현장에서는 70% 상한 운용, 자동 DoS 판정, 자동 재시작, 자동 쿼리제거 같은 자율제어를 적용하지만, 이런 장치는 어디까지나 잠정적 대응이며 근본적인 해결은 코드와 설계 개선이라는 점을 잊지 않는 것이 중요합니다.

Reference