개발일지
클러스터링, 로드밸런싱으로 서버 성능 개선하기 (PM2, LB, 고가용성, 가용 영역) 본문
개요
여태껏 서버를 배포한다고 하면 EC2 인스턴스 하나 생성해서 PM2 무중단 배포한게 전부였다. 하지만 실무에 들어가보니 최소 두 개 이상의 인스턴스에 로드밸런싱 하는 것을 볼 수 있었다. 몰려드는 트래픽에 대비해 서버 부하를 줄이기 위한 목적으로 로드밸런싱 한다는 건 알고 있었지만, 공부해보니 “고가용성”이라는 아주 중요한 이유가 하나 더 있었다. PM2 무중단 배포 역시 고가용성 확보를 위한 한 가지 방법이었다.
이번 시간에는 고가용성에 대해 알아보고 이를 위한 아키텍처 구축 방법에 대해 알아보고자 한다.
고가용성(High Availability, HA) 이란?
서버, 네트워크, 프로그램 등의 시스템이 최소한의 다운타임(Down Time)으로 지속적으로 정상 운영될 수 있는 능력을 의미한다. 고가용성은 두가지 측면이 고려될 수 있는데 첫번째는 앞서 말한 것처럼 “다운타임이 거의 없이 운영 가능한가”이다. 그리고 시스템이 운영되는 동안 “얼마나 합리적인 성능을 제공하는가”이다.
대표적인 방법으로 로드밸런서를 이용해 서버 부하를 분산하는 방법이 있다. 이번 시간에는 PM2, 로드밸런서 등을 사용해서 보다 안정적이고 효율적인 서버로 개선해보고자 한다.
PM2 클러스터 모드 적용하기
기본적으로 Node.js는 싱글스레드 방식이기때문에 VM의 CPU가 여러개더라도 이를 활용할 수가 없다. 이러한 한계를 극복하는 방법으로 서버를 여러개 띄운 후 Reverse Proxy 서버로 로드밸런싱 해주는 방법이 있다. 하지만 이 방법은 개발자가 하나하나 다 설정하고 관리해줘야하기 때문에 번거롭다.
또 다른 방법은 PM2에서 지원하는 클러스터 모드를 설정해주는 것이다. 다음과 같은 명령어로 쉽게 클러스터를 적용해줄 수 있다.
$ pm2 start build/index.js -i 2
- -i : 띄울 인스턴스 수, 숫자 대신 “max”를 입력하면 사용할 수 있는 최대 cpu 코어를 사용한다.
pm2 list로 확인해보면 프로세스가 여러 개이고 cluster 모드로 돌아가고 있는 것을 볼 수 있다.
클러스터링 전후 동작 구조를 비교해보면 다음과 같다.
수직 확장(Vertical Scaling, 또는 Scale up) vs. 수평 확장(Horizontal Scaling, 또는 Scale out)
서버를 확장하기 위한 방식으로 수직 확장과 수평 확장이 있다. 수직 확장은 단일 서버 사양 자체를 업그레이드 하는 방식이고 수평 확장은 비슷한 사양의 서버를 여러 개 사용하는 방식이다. 가급적이면 수직 확장보다는 수평 확장을 사용하는 게 비용 측면이나 확장성 및 유연성 등에서 더 유리한 경우가 많다.
앞서 적용한 PM2 클러스터 모드도 수평 확장 방식 중 하나라 볼 수 있다. 하지만 클러스터 모드만으로는 가용성을 높이는 데 한계가 있다. 한 VM 안에서 이뤄지기 때문에 만약 서버 자체에 문제가 생겨버리면 결국은 서비스 자체가 다운되어 버린다.
이러한 한계를 보완하기 위해 로드밸런서를 사용해서 수평 확장 해보고자 한다. 즉 동일한 인스턴스을 여러 개 생성한 뒤 LB를 사용하여 요청을 고르게 분산해줄 수 있도록 구현할 것이다.
Snapshot, 로드밸런서로 서버 부하 분산하기
하나의 서버를 배포하기 위해서는 인스턴스 생성, SSH 등록, 프로젝트 배포 등 일련의 과정이 필요한데 이걸 서버 하나 추가할 때마다 반복하는 것은 조금 귀찮은 일이다. 하지만 인스턴스의 스냅샷을 생성하여 동일한 환경의 인스턴스를 손쉽게 복제할 수 있다.
복제할 인스턴스 > Snapshots 탭 > Create snapshot > Create new instance 로 새로운 인스턴스를 생성해주자.
생성 후 Instances 대시보드를 보면 새로운 인스턴스가 추가되어있을 것이다. 터미널에 접속해 ls 명령어를 입력해보면 복제한 인스턴스와 동일한 구조인 것을 확인할 수 있다.
마지막으로 생성한 인스턴스들을 로드밸런서에 추가 등록해주면 된다. Networking > 사용할 로드밸런서 > Attach another를 클릭하고 Health Check까지 성공하면 끝이다.
이제 들어오는 요청을 LB가 알아서 분산해줄 것이다.
클러스터링, 로드밸런싱까지 적용해줬지만 아직도 한계가 존재한다. 인스턴스들이 하나의 가용 영역을 사용하고 있다는 것이다. 매우 중요하지만 나같은 입문자들을 무심코 넘어갈 수 있는 개념이기에 짚고 넘어가고자 한다.
가용 영역(Availability Zones, AZ)
인스턴스를 생성할 때 보면 리전(Region)과 함께 가용 영역(AZ)이라는 걸 선택하게 되어있다. 리전과 AZ 모두 서버의 물리적인 위치를 의미한다. 다만 리전이 국가/도시 단위의 지리적 위치라면 가용 영역은 각 리전 안의 데이터센터를 말한다.
즉 아래의 사진을 보면 현재 Seoul 리전에는 네군데의 데이터센터가 존재한다는 것을 알 수 있다.
하지만 이걸 모른 채 모든 인스턴스를 Zone A에 만들게 된다면? 해당 데이터 센터에 문제가 생겼을 때 로드밸런싱이고 자시고 서비스 전체가 다운되어버리는 것이다. 따라서 각 인스턴스가 다른 가용영역을 사용하도록 생성해줘야한다.
성능 개선 결과
마지막으로 VM 배포만 했을 때, PM2 클러스터링 적용 후, 로드밸런싱 적용 후 응답 시간을 비교해보고 마무리 하겠다. 부하테스트에는 artillery를 사용했다.
VM 배포만 했을 때
걍 실패...
PM2 클러스터링 적용 후
응답이 오긴 하지만 응답시간(http.response_time)도 길고 아직까지 타임아웃도 빈번히 난다.
로드밸런싱 적용 후
타임아웃도 없고 응답시간도 평균값(mean) 기준 약 76%, 중앙값(median) 기준 약 89%가 개선되었다.
'Infra, AWS, Linux' 카테고리의 다른 글
메모리 부족으로 인한 VSCode SSH 끊김 현상(OfflineError) 해결하기- Swap 메모리 (0) | 2025.02.22 |
---|---|
컨테이너 기반 CI/CD 구축해보기 - AWS ECR, ECS, Github Actions (0) | 2024.07.11 |
AWS Lightsail로 CI/CD 구축하기_2. Github Actions으로 배포 자동화 파이프라인 구축하기 (0) | 2024.06.16 |
AWS Lightsail로 CI/CD 구축하기_1. Ligthtsail 생성 및 SSH 접속하기 (0) | 2024.06.05 |
AWS SSM으로 Private RDS 접근하기 (0) | 2024.02.02 |