CS/SRE

Ch20. 데이터센터의 로드밸런싱

12.tka 2023. 10. 11. 09:56
728x90

이번 장에서는 데이터센터 내에서의 로드밸런싱에 대해 알아보도록 하자. 특히 지정된 데이터센터 내에서 쿼리 스트림을 효과적으로 분산 처리하기 위한 알고리즘과 요청이 유입될 때 이를 처리할 수 있는 개별 서버로 라우팅 하는 애플리케이션 수준 정책에 대한 내용을 중점적으로 살펴보자.

 

양호하지 않은 태스크 구별하기

클라이언트의 요청을 어느 백엔드가 처리할 것인지 결정하기 위해서는 그 전에 백엔드 풀에서 양호하지 않은 태스크를 식별할 필요가 있다.

 

1. 흐름 제어

활성화된 요청의 개수가 설정된 한계 값을 넘어서면 클아이언트는 백엔드가 양호하지 않은 상태에 있다고 가정하고 더 이상 요청을 전달하지 않는다. 이와 같은 엄청 간단한 흐름 제어는 간단한 형태의 로드밸런싱이라고 보아도 무방하다.

 

위 방법은 매우 높은 수준의 과부하 상태에서 백엔드 태스크만을 보호할 수 있다. 또한 이 한계값에 도달하기 전에 이미 백엔드가 과부하 상태에 놓이기도 쉽다. 물론 반대의 경우도 가능하다.

 

2. 레임덕 상태

레임덕 상태는 백엔드 태스크가 포트를 리스닝 중이고 서비스를 제공할 수 있지만 명시적으로 클라이언트에게 요청의 전달을 중단할 것을 요구하는 상태를 말한다.

 

태스크가 레임덕이라는 다소 어중간한 상태를 갖는 것을 허용함으로써 얻을 수 있는 장점은 셧다운 과정을 깔끔하게 처리하는 것이 쉬워진다는 것이다. 참고로 태스크의 셧다운은 일반적으로 아래 절차를 따른다.

  1. 잡 스케줄러가 SIGTERM 신호를 백엔드 태스크에 전달
  2. 백엔드 태스크 레임덕 상태로 전환되고 클라이언트들에게 요청을 다른 백엔드 태스크로 전달할 것을 알린다.
  3. 백엔드 태스크가 레임덕 상태로 전환되기 전에 처리 중이던 요청들은 정상적으로 실행된다.
  4. 클라이언트에 응답을 전달하다 보면 해당 백엔드에 남은 활성화된 요청의 개수는 0으로 줄어든다.
  5. 설정된 일정 시간을 기다린 다음, 백엔드 태스크는 깔끔하게 종료되거나 혹은 잡 스케줄러가 태스크를 종료한다.

 

서브셋을 이용한 연결 풀 제한하기

서브셋은 클라이언트 태스크와 상호작용할 잠재적인 백엔드 태스크들의 풀을 제한하는 것과 관련 있다. 서브셋을 활용하면 하나의 클라이언트가 많은 수의 백엔드 태스크에 연결되거나 혹은 하나의 백엔드 태스크가 많은 수의 클라이언트 태스크들의 연결을 수용할 수 있게 할 수 있다.

 

적절한 서브셋 선택하기

적절한 서브셋을 선택하려면 각 클라이언트 연결이 얼마나 많은 백엔드 태스크에 연결될 것인지를 선택해야 하며, 선택 알고리즘 역시 구현되어야 한다. 선택 알고리즘은 크게 랜덤 서브셋, 결정적 서브셋이 있다.

 

랜덤 서브셋

각 클라이언트가 백엔드의 목록을 임의로 섞은 후, 그중에서 접근이 가능하고 양호한 상태의 백엔드를 선택해서 서브셋을 구축하는 방법이다. 한 번 임의로 섞은 후 백엔드를 차례로 선택하는 방법은 고려 대상이 될 백엔드의 수를 명시적으로 제한할 수 있으므로 재시작과 장애 상황을 안정적으로 처리할 수 있다. 그러나 이 전략은 부하가 균등하게 분산되지 않기 때문에 대부분의 경우에 원하는 대로 동작하지 않는다는 것을 경험했다.

 

랜덤 서브셋을 구현하고 다양한 경우의 수에 대한 테스트를 수행해보니 작은 크기의 서브셋을 사용하면 불균형이 더 심해지는 현상이 발생하였다. 결국 랜덤 서브셋을 이용해 가용한 태스크들을 상대적으로 균형 있게 처리하려면 서브셋의 크기는 대략 75% 정도가 되어야 한다는 결론을 내렸다. 문제는 서브셋을 그 정도로 크게 설정하면 효율이 크게 떨어진다는 점이다. 태스크에 연결되는 클라이언트의 수의 변동폭이 너무 크기 때문에 대용량 환경에서 적절한 랜덤 서브셋을 선택하는 적절한 정책을 수립하기가 어렵다.

 

결정적 서브셋

결정적 서브넷은 랜덤 서브셋의 제한을 해결하기 위한 해결책이다. 클라이언트 태스크들을 '라운드'로 나누어 사용한다. 이를 통해 각 백엔드는 정확히 하나의 클라이언트에 할당된다. 

 

중요한 것은 백엔드의 목록은 반드시 섞여야 한다는 점이다. 그렇지 않으면 클라이언트가 할당된 연속적인 백엔드 태스크의 그룹에 공교롭게도 현재 사용 가능한 백엔드가 존재하지 않을 수 있다. 각 라운드는 목록을 혼합할 때 각기 다른 시드 값을 사용한다. 그렇지 않으면 백엔드가 실패했을 때 해당 백엔드의 부하는 서브셋에 남아있는 백엔드 중 하나가 부담해야 한다. 만일 서브셋 내의 다른 백엔드마저 실패한다면 그 영향이 더해져 상황이 더 빠르게 악화될 수 있다. 예를 들어 어느 서브셋에 포함된 백엔드 N이 다운된다면, 그에 상응하는 부하가 남은 백엔드로 퍼져나가게 된다. 더 나은 방법은 이 부하를 각 라운드마다 매번 목록을 다르게 뒤섞어 남아있는 백엔드 전체에 부하를 분산하는 방법이다.

 

로드밸런싱 정책

로드밸런싱 정책은 클라이언트 태스크들이 자신의 서브셋 내에서 요청을 처리할 백엔드를 선택하기 위해 사용하는 메커니즘이다. 로드밸런싱 정책의 복잡성 중 상당 부분은 클라이언트가 각 요청을 어떤 백엔드가 처리할 것인지를 실시간으로 결정해야하는 의사 결정 프로세스가 본질적으로 분산되어 있기 때문에 발생한다.

 

로드밸런싱 정책은 백엔드의 상태에 대한 어떤 정보도 필요하지 않은 간단한 방법(라운드 로빈)부터 백엔드에 대한 더 자세한 정보를 필요로 하는 방법(최소 부하 라운드 로빈 혹은 가중 라운드 로빈)이 있다.

 

간단한 라운드 로빈

모든 클라이언트가 동일한 비율로 요청을 보내지 않을 수도 있기 때문에 부하 조정 능력이 떨어진다. 그뿐만 아니라 같은 데이터센터 내의 모든 머신이 완전히 동일하지 않을 수 있기 때문에 같은 요청이 어떤 머신에서는 상당히 다른 양의 작업이 될 수 있다.

 

최소 부하 라운드 로빈

간단한 라운드 로빈의 대안으로는 각 클라이언트가 서브셋 내의 각 백엔드 태스크와 연결된 활성화된 요청의 개수를 추적하고 가장 적은 수의 활성화된 요청을 처리하고 있는 태스크들만을 대상으로 라운드 로빈을 수행하는 것이다.

 

최소 부하 정책의 핵심은 부하가 많은 태스크들은 여럭이 있는 태스크들보다 상대적으로 지연응답률이 높기 때문에 부하가 많은 태스크들을 을 제외하는 것이다.

 

만일 어느 태스크가 심각하게 양호하지 않은 상태라면, 이 태스크는 100%의 확률로 에러를 발생시킬 수도 있다. 이를 통해 낮은 지연응답률을 가질 수 있는데 그 결과 이 태스크는 트래픽을 마치 싱크홀처럼 빨아들이게 된다. 다행인 것은 이 함정은 활성화된 요청을 최근 리턴받은 에러의 개수를 추적하도록 정책을 수정함으로써 상대적으로 쉽게 해결할 수 있다.

 

 

가중 라운드 로빈

앞서 설명한 두 가지 라운드 로빈 정책에 비해 백엔드가 제공하는 정보를 의사결정 프로세스에 반영하는 중요한 로드밸런싱 정책이다. 실질적으로 가중 라운드 로빈은 아주 잘 동작하며 최저 및 최고 부하 태스크 사이의 간극을 잘 메워준다.

 

정리

양호한 태스크를 구별하는 방법을 통해 태스크를 적절하게 관리할 수 있는 방법을 알게 되었고, 로드 밸런싱 정책의 다양한 방법을 알게 되었다.

728x90

'CS > SRE' 카테고리의 다른 글

Ch22. 연속적 장애 다루기  (0) 2023.10.18
Ch21. 과부하 처리하기  (0) 2023.10.11
Ch19. 프론트엔드의 로드밸런싱  (0) 2023.10.11
Ch18. SRE 조직의 소프트웨어 엔지니어링  (0) 2023.08.30
Ch17. 신뢰성을 위한 테스트  (0) 2023.08.30