CS/SRE

Ch22. 연속적 장애 다루기

12.tka 2023. 10. 18. 20:54
728x90

연속적 장애는 정상적인 것처럼 보이는 응답 때문에 시간이 지나면서 장애가 계속해서 가중되는 현상이다. 전체 시스템의 일부에서 장애가 발생했을 때 주로 나타나며, 이로 인해 시스템의 다른 부분에 장애가 발생할 가능성도 늘어나게 된다.

 

연속적 장애의 원인과 대책

서버 과부하

연속적 장애를 유발하는 가장 일반적인 원인은 과부하다. 예를 들어 한 클러스터에서 과부하가 발생하면 그 서버들이 충돌로 인해 강제로 종료되게 되고 그 여파로 로드밸런싱 컨트롤러가 요청을 다른 클러스터에 보내면 그쪽의 서버들에게 과부하가 발생하고 결국 서비스 전체에 걸친 과부하 장애가 발생한다.

 

자원의 부족

자원 부족으로 인해서 높은 지연응답과 에러율의 증가 혹은 낮은 품질의 응답을 야기할 수 있다. 이러한 현상이 발생하면 성공적으로 처리된 요청의 비율이 빠르게 낮아지고 클러스터 혹은 전체 서비스에 연속적 장애가 발생하게 된다.

 

서버 과부하 방지하기

테스트

테스트는 서버의 과부하를 방지하기 위해 반드시 수행해야 할 가장 중요한 사안이다. 실제 환경에서 테스트하지 않으면 정확히 어떤 자원이 부족해지는지, 그리고 자원의 부족이 어떤 영향을 미치는지 예측하기가 어렵다. 그렇기 때문에 실제 환경에서 다양한 케이스를 테스트함으로써 서버 과부하 원인을 파악하고 미리 방지하는 것은 아주 중요하다.

 

경감된 응답 제공

품질은 낮지만 더 수월하게 연산할 수 있는 결과를 사용자에게 제공한다. 이 전략은 서비스마다 다르게 적용될 수 있기 때문에 상황에 맞게 유연하게 제공하면 된다.

 

과부하 상태에서 요청을 거부하도록 서비스 구현

프론트 혹은 백엔드에 과부하가 발생하면 최대한 빠르면서도 비용이 적게 드는 방법으로 실패를 처리해야 한다. 

 

수용량 계획 실행

수용량 계획을 제대로 실행하면 연속적 장애의 가능성을 줄일 수 있다. 수용량 계획은 서비스가 어느 수준의 부하에서 장애가 발생하는지를 판단하기 위해 반드시 성능 테스트와 병행되어야 한다. 수용량 계획은 연속적 장애의 발생 가능성을 억제할 수는 있지만, 연속적 장애로부터 시스템을 보호하는 데는 크게 도움이 되지 않는다. 계획된 혹은 예상치 못한 현상으로 인해 인프라 스트럭처의 상당 부분에서 장애가 발생했다면 수용량 계획을 잘 수립했더라도 연속적 장애를 해결하지는 못할 것이다.

 

부하 제한과 적절한 퇴보 (+재시도)

부하 제한

서버가 과부하 상태에 도달하게 되면 부하 제한을 통해 유입되는 트래픽을 감소시켜 어느 정도의 부하를 덜어낼 수 있다. 그 목적은 서버의 메모리 부족이나 건강 상태 점검 실패, 지연 응답의 극단적 증가 및 기타 과부하에 관련된 증상들이 서버에서 발생하는 것을 방지하고 서버가 최대한 자신의 작업을 계속해서 수행할 수 있도록 유지하는 것이다.

 

적절한 퇴보

부하 제한의 개념에서 한 걸음 더 나아가 실행해야 할 작업의 양을 감소시키는 방법이다. 일부 애플리케이션의 경우 일부러 응답의 품질을 경감시켜 작업의 양이나 처리에 필요한 시간의 양을 현저히 줄일 수 있다. 예를 들어 검색 애플리케이션은 디스크 상의 전체 데이터베이스가 아닌 메모리 캐싱에 저장된 일부 데이터에 대해서만 검색을 수행한다거나 과부하 시에 비교적 정확도가 떨어지지만 더 빠른 순위 알고리즘을 적용할 수 있다.

 

재시도

자동 재시도를 수행할 경우 서버 수준에서 재시도에 대한 한계 수치를 책정하는 것이 좋다. 제한 없이 재시도를 계속 수행하게 둔다면 이는 연속적 장애를 유발할 수도 있기 때문이다.

 

마감기한

마감기한을 설정하지 않거나 혹은 너무 긴 시간을 설정하면 서버가 재시작할 때까지 서버의 자원을 오랫동안 계속해서 소비하게 되는 문제가 단기적으로 발생할 수 있다. 따라서 적절한 마감기한을 설정하는 것이 효율적으로 자원을 사용하는 방법 중 하나이다. 마감기한이 지난 경우 해당 요청은 의미가 없기 때문에 마감기한이 지났는지 잘 전파하는 것도 중요하다.

 

콜드 캐싱

콜드 캐시를 갖게 되는 경우는 다음과 같다.

  • 새로운 클러스터를 켜는 경우: 완전히 비어있는 캐시와 함께 실행
  • 유지보수 작업 후 클러스터를 서비스에 제공: 캐시의 데이터가 유용하지 않을 수 있는 상태
  • 서비스 재시작: 캐시를 다시 채우는 데 어느 정도의 시간이 필요

만약 캐시가 서비스에 중요한 영향을 미친다면 클러스터의 부하 크기를 천천히 늘려주면서 캐시가 어느 정도 채워진 후 많은 트래픽을 처리하도록 구성하는 방법도 좋다.

 

연속적 장애 테스트하기

장애가 발생할 때까지 테스트하고 조치

컴포넌트에 장애가 생길 때까지 부하 테스트를 진행하는 방법이다. 부하가 증가하면 대부분의 컴포넌트는 요청을 성공적으로 처리하다가 어느 시점부터 더 이상의 요청을 처리하지 못하게 된다. 이상적인 컴포넌트는 이 시점에서 성공적으로 처리하는 요청의 양이 크게 줄지 않으면서도 부하의 한계를 넘어선 요청에 대해서는 에러 혹은 경감된 결과를 리턴해야 한다.

 

이러한 테스트를 통해 어느 지점에서 장애가 발생하는 지 확인하고 수용량 계획을 세울 수도 있고 장애를 방지하는 다른 방법에 대해서도 고민해 볼 수 있다.

 

상대적으로 덜 중요한 백엔드 테스트

상대적으로 덜 중요한 백엔드 테스트에 대한 테스트를 통해 이 백엔드가 사용 불가능한 상태라 하더라도 서비스의 중요한 컴포넌트들이 그에 따른 간섭을 받지 않는지 확인하는 테스트이다.

 

연속적 장애를 처리하기 위한 즉각적인 대처

자원의 추가 투입

여분의 자원에 태스크를 추가하는 방법이다. 하지만 서비스가 죽음의 소용돌이에 휘말렸다면 자원을 추가한다고 해서 장애로부터 벗어날 수는 없을 것이다.

 

건강 상태 점검 중지

서비스가 건강 상태가 아닌 경우 건강 상태 점검으로 인해 장애 모드로 들어갈 수 있다. 그렇기 때문에 건강 상태 점검을 일시적으로 중지해서 모든 태스크가 실행될 때까지 시스템이 안정적으로 동작하도록 할 수 있다.

 

서버의 재시작

서버 재시작으로 장애를 처리하기 전에 연속적 장애의 원인을 먼저 규명해야 한다. 단순히 재시작을 해서 장애를 해결했더라도 원인을 모르면 다음에도 장애가 발생할 수 있기 때문이다. 그리고 콜드캐시 같은 이슈라면 서버의 재시작은 오히려 연속적 장애를 더 크게 만들 수 있기 때문에 재시작으로 장애를 처리하기 위해서는 꼭 원인을 먼저 규명해야 한다.

 

트래픽의 경감

아래 과정을 통해 부하가 정상적인 수준으로 돌아올 때까지 서버가 실행을 준비하고 필요한 연결을 수립하는 등의 작업을 처리할 여력을 갖게 된다.

  1. 장애를 유발하는 기본적인 원인을 처리한다.
  2. 충돌이 사라질 만큼 충분히 부하를 경감시킨다. 이때는 적극적이어야 한다. 만일 전체 서비스에서 계속 충돌이 발생한다면 전체 트래픽의 1%만을 처리하도록 조치한다.
  3. 대부분의 서버가 양호한 상태가 된다.
  4. 점진적으로 서버에 부하를 늘려간다.

이외에도 위에서 언급했던 퇴보 모드로 돌아가기를 포함해서 일괄 작업 부하 배제, 문제 있는 트래픽 배제 등의 방법이 있다.

 

정리

이번 장에서는 연속적 장애의 원인과 대처 방법에 대해서 알아보았다. 장애이지만 정상적인 것처럼 보이는 응답을 빠르게 파악하는 것이 중요할 것 같고 연속적 장애를 대비하기 위해서 미리 테스트해보고 올바른 수용량 계획을 세우는 것이 중요할 것 같다.

 

장애가 발생했을 때는 재시작을 바로 하기보다는 원인을 파악한 후 적절한 조치를 취하도록 해야겠다. 그리고 마지막에 서비스가 장애가 발생할 수 있는 수준에 도달하면 사용자의 모든 요청을 완벽하게 처리해 내기보다는 에러를 리턴하거나 혹은 평소 대비 낮은 품질의 결과를 리턴해야 한다고 적혀있는데 이 부분은 어떤 서비스인지에 따라서 다를 것 같다. 사내에 제공하고 있는 서비스는 모든 요청을 완벽하게 처리해야 할 필요도 있기 때문이다.

728x90