컴퓨터공학과 21411861 신수형
1. 부하분산기의 역할과 목적
로드밸런싱은 여러 대의 서버를 두고 서비스를 제공하는 분산 처리 시스템에서 필요한 기술이다.
로드밸런싱은 항상 필요한가?
서비스의 제공 초기 단계라면 적은 수의 클라이언트로 인해 서버 한 대로 요청에 응답하는 것이 가능하다. 하지만 사업의 규모가 확장되고, 클라이언트의 수가 늘어나게 되면 기존 서버만으로는 정상적인 서비스가 불가능하게 된다. 이처럼 증가한 트래픽에 대처할 수 있는 방법은 크게 두 가지이다.
scale-up 의 경우 서버 자체의 성능을 확장하는 것을 의미한다. 비유하자면 CPU가 i3인 컴퓨터를 i7으로 업그레이드하는 것과 같다.
scale-out의 경우 기존 서버와 동일하거나 낮은 성능의 서버를 두 대 이상 증설하여 운영하는 것을 의미한다. CPU가 i3인 컴퓨터를 여러 대 추가 구입해 운영하 것에 비유할 수 있다.
sacle-out 의 방식으로 서버를 증설하기로 결정했다면 여러 대의 서버로 트래픽을 균등하게 분산해주는 로드밸런서가 필요한 것이다.
2. 부하분산기 생성 과정
부하분산기를 운영하려면, 실제로 서비스를 제공할 인스턴스를 만들어야 한다. ‘분산’이 목표이기 때문에 하나의 인스턴스가 아니라 여러개의 인스턴스에 동일한 서비스를 배포해서 하나의 그룹으로 묶어주는 과정이 필요하다. 하지만 지금은 로드밸런서가 정상적으로 동작하는지 확인하는 과정이기 때문에 두개의 인스턴스에 각각 다른 서비스를 배포하려고 한다.
클라우드 서비스는 Google Cloud Platform을 활용했다. 활용한 솔루션은 VM 인스턴스, 인스턴스 그룹, 고정 ip 그리고 로드밸런서이다.
1) 인스턴스 생성
VM인스턴스를 생성한다. 이름에 학번을 활용해서 생성자를 확인할 수 있도록 하였다. HTTP 방화벽 연결을 설정해 주었다. SSL등록이 되어있지 않기 때문에 HTTPS 방화벽 설정은 등록하더라도 사용할 수 없다.
현재 HTTP 포트(80)만 열려있기 때문에 추후 서버 배포는 80포트에 바로 달거나 nginx를 통해 리버스 프록시를 등록해야한다.
2) 인스턴스 그룹 생성
이제 부하분산기에서 활용할 인스턴스 그룹을 만들어주어야한다.
그룹을 생성한 후 그룹 수정→ 구성원 추가를 활용해 위에서 생성한 두 인스턴스를 추가해준다. 아래 사진처럼 그룹 구성원이 추가된 것을 확인할 수 있다.
3) 고정 ip 생성
각 인스턴스는 이미 접속할 수 있는 고정 IP가 있지만, 부하분산기로 접속할 때 필요한 고정 IP는 따로 생성해주어야 한다. 미리 고정 IP를 생성해두면 편하기 때문에 고정 IP를 생성해두자.
이제 이 고정 IP를 활용해 부하분산기를 만들어볼 예정이다.
4) 부하분산기(load balancer) 생성
네트워크 솔루션 → 부하분산기 만들기에서 부하분산기를 생성한다. HTTP(S) 어플리케이션에 대해 만들 것이기 때문에 첫번째 구성으로 시작한다.
프론트엔드 구성은 유저가 접속할 엔드포인트에 대한 구성이다. 이전에 만들어둔 고정 IP를 등록해서 엔드포인트 구성을 마무리한다. 백엔드 구성은 서버가 응답할 엔드포인트에 대한 구성이다. 인스턴스 그룹을 활용한 테스트를 진행할 것이기 때문에 인스턴스 그룹, 그리고 만들어둔 그룹을 선택한다.
이제 아래처럼 부하분산기가 생성된 것을 확인할 수 있다.
상세 정보에 들어가면 프론트엔드 접속 포트와 백엔드 인스턴스 그룹 구성, 그리고 해당 인스턴스들의 상태를 확인할 수 있다.
5) 부하분산기 동작을 확인 위한 인스턴스 그룹별 웹 서버 빌드 및 배포
가장 간단하게 확인하기 위해서 웹 서버를 만들어보자. 위에서 80포트만 열었기 때문에 서비스를 배포한 후, reverse proxy를 활용하거나 직접 80포트로 배포해야한다. 이번에는 웹 client server를 원하는 포트로 바로 배포할 수 있는 React를 활용하기로 하였다. 필요한 패키지를 설치한다.
sudo apt install nodejs
sudo apt install npm
sudo npm install -g n
sudo npx create-react-app {app-name}
cd {app-name}
sudo npm run build # React client build
sudo npx serve -l 80 -s build # build 파일을 80 포트로 배포
Shell
복사
정상적으로 Serving이 되는 것을 확인할 수 있다. 동일하게 다른 인스턴스도 작업한다. 하지만 같은 화면이 나오면 비교가 안되기 때문에 코드를 조금 수정해서 두 인스턴스가 다른 웹 클라이언트를 서빙할 수 있도록 해준다.
위에는 로컬 IP가 나와있다. 외부에서 접속하려면 외부 IP를 활용해야 한다. 우리는 부하분산기 고정 IP를 등록해뒀기 때문에 해당 IP를 사용하면 된다.
3. 부하분산기 결과 확인 및 발생 원인 분석
접속 링크 : http://34.111.147.220
부하분산 테스트
새로고침을 해서 새로운 요청이 갈 때마다, 부하분산기가 동작하는 것 을 확인할 수 있다. 아래 refresh 버튼을 누르거나 cmd + f5(브라우저 새로고침)을 눌러서 확인할 수 있다.
왼쪽은 첫번째 인스턴스 (id : yu-21411861) 오른쪽은 두번째 인스턴스(id: yu-21411861-2)에 들어온 요청이다. 부하분산기가 정상적으로 동작하고 있는 것을 로그를 통해 확인할 수 있다. 현재는 / 에 대한 요청밖에 없어서 큰 차이가 없지만, GET / → GET /logo.svg 와 같이 여러개의 요청이 들어온 경우, 서로 다른 인스턴스에서 각각 하나씩 맡아서 요청을 처리하고 응답을 보내주기도 한다. 즉, 로드벨런서는 실제로 사용자가 보낸 요청 뿐 만 아니라, 해당 요청이 참조하는 다른 요청들에 대해서도 부하분산을 해준다.
첫번째 인스턴스의 end point를 찾을 수 없다면?
인스턴스 그룹에 2개의 인스턴스가 등록되어 있으나, 첫번째 인스턴스를 종료한다면 어떻게 될까? 확인해봤더니 응답 에러를 내보내는 것이 아니라 살아있는 end point의 응답만 보내준다. 아래 로그를 보면 왼쪽 인스턴스에 배포중인 서버를 종료한뒤 테스트를 진행했을 때, 오른쪽으로만 접속이 되는 것을 볼 수 있다. 이렇게 부하분산기를 운영하면, 서버가 부득이한 이유로 종료되거나 버전 업을 위해 잠시 배포를 중단한 상황에서도 실제 사용자는 정상적으로 서비스를 제공받을 수 있다.
위 상황에서 두번째 인스턴스에서 배포중인 서비스에서만 응답이 오는 장면이다.
stress test
부하분산기 stress test를 진행해 보았다.
동일하게 왼쪽은 첫번째 인스턴스 오른쪽은 두번째 인스턴스이다.
여기서 첫번째 인스턴스에 stress 명령을 활용해 cpu사용량을 100%로 올려보았다. 왼쪽 아래 htop을 보면 cpu사용량이 100%가 된 것을 확인할 수 있다. 그리고 다시 요청을 보내보았다.
분산 결과는 동일했다. 10번 시도했을 때 각각 5번의 요청을 응답했다. 하지만 응답속도에서는 차이가 있었다. 첫번째 인스턴스가 평균적으로 1ms정도 더 늦게 응답을 보낸것을 확인할 수 있다. 만약 서빙하는 파일의 용량이 크거나 처리해야할 로직이 복잡하다면, 이 차이가 더 커질 수 있을 것 같다.
그런데 이러한 결과는 기대한 상황이 아니다. 하나의 인스턴스가 cpu사용량이 늘어나면 cpu사용량이 적은 인스턴스쪽으로 분산시키는 것을 기대했다. 아무래도 처리 속도가 너무 빨라서 분산까지 되는 상황을 측정하지 못한 것 같다.