서버 부하 분산 적용기

[#🐬Board] 대용량 트래픽에 대비한 Nginx 로드밸런싱

Board 서버에 부하 분산 적용한 이유는 다음과 같습니다.

  • 고가용성: 단일 서버라면 그 자체가 SPOF가 될 수 있습니다. 부하 분산을 통해 하나의 서버가 다운될 경우, 다른 서버로 Fail Over 할 수 있습니다. 장기적으로 무중단 배포를 위해 꼭 해야 했던 작업입니다.

  • 성능 향상: 여러 서버에 트래픽을 분산시켜 각 서버가 더 적은 작업을 처리하게 합니다. 응답 시간을 줄이고 전체 서비스의 성능을 향상시킬 수 있습니다.

  • 확장성: 증가하는 트래픽을 처리하기 위해 서버를 추가하여 Scale Out이 용이합니다.

HAProxy 대신 Nginx를 선택한 이유는 다음과 같습니다.

  • 설치 및 설정 간편성: 가장 중요한 이유입니다. 더 대중적이기 때문에 레퍼런스가 더 많습니다. 인프라 작업에 많은 시간을 소모하고 싶지 않기 때문에 대중적인 선택을 했습니다.

  • 웹 서버: Nginx가 웹 서버 기능을 제공하기 때문에 이후 다른 기능을 추가할 때 더 유연하게 변경할 수 있다고 느꼈습니다.

💡개발 환경

운영체제: Debian GNU/Linux 11, Nginx: 1.18.0

💡upstream block 설정

upstream board { # upstream 블록 정의
    # WAS가 떠있는 서버의 외부 IP를 기입합니다.
    server was-a-ip:8080;
    server was-b-ip:8080;
    server was-c-ip:8080;
}

VM 인스턴스 한 대당 WAS 1대를 띄웠습니다. upstream 서버에서는 기본적으로 Round Robin 방식으로 각각의 WAS에 요청을 분산시켜줍니다. 다른 LB 메소드가 몇몇 있긴 하지만, 수정할 필요를 못 느꼈기 때문에 기본값으로 진행했습니다.

아래처럼 더 많은 설정을 구성할 수도 있습니다.

upstream board {
    zone upstream_dynamic 64k;  # 메모리에 64KB의 공간을 가진 upstream_dynamic 영역을 정의합니다.

    server was-a-ip weight=5;  # was-a-ip 서버를 가중치 5로 추가합니다.
    server was-b-ip:8080 fail_timeout=5s slow_start=30s;  # was-b-ip의 8080 포트에 접속합니다. 연결 실패 시 5초간 대기하고, 천천히 시작합니다.
    server 192.0.2.1 max_fails=3;  # 192.0.2.1 주소를 가진 서버를 추가하며, 최대 3번의 연속 실패 허용합니다.
    server was-c-ip resolve;  # was-c-ip을 동적으로 해석하여 서버로 추가합니다.
    server was-d-ip service=http resolve;  # was-d-ip을 HTTP로 서비스하며 동적으로 해석하여 서버로 추가합니다.

    server backup1.example.com:8080 backup;  # backup1.example.com의 8080 포트를 백업 서버로 추가합니다.
    server backup2.example.com:8080 backup;  # backup2.example.com의 8080 포트를 백업 서버로 추가합니다.
}

💡server block 설정

server {
    listen 80;               # IPV4 주소로 80 포트를 듣습니다.
    listen [::1]:80;         # IPv6 주소로 80 포트를 듣습니다.
    server_name localhost;   # 이 서버 블록은 localhost에 대한 요청을 처리합니다.

    location / {
        include /etc/nginx/proxy_params;  # proxy 설정 파일을 포함합니다.
        proxy_set_header Connection "";   # Connection 헤더를 비웁니다.
        proxy_pass http://board;         # proxy_pass로 정의한 upstream인 board로 요청을 전달합니다.
    }
}

💡테스트

수정사항을 반영하기 위해 Nginx를 리로드합니다.

sudo service nginx reload

이후 엔드포인트에 GET 요청을 보내서 body를 확인해보면, 다음과 같이 upstream에서 설정했던 서버 3대를 돌아가며 접속되는 것을 확인할 수 있습니다.

$ curl -s https://board.jiseunghyeon.site
<p>If you see this page, the board api a-server is successfully working.</p>
$ curl -s https://board.jiseunghyeon.site
<p>If you see this page, the board api b-server is successfully working.</p>
$ curl -s https://board.jiseunghyeon.site
<p>If you see this page, the board api c-server is successfully working.</p>
$ curl -s https://board.jiseunghyeon.site
<p>If you see this page, the board api a-server is successfully working.</p>

🎯정리

  • Nginx 로드밸런싱을 통해 게시판 서버 1대가 다운될 경우, 다른 서버가 계속 서비스할 수 있도록 구성합니다.

  • 트래픽을 분산시켜 각각의 WAS가 더 적은 작업을 처리하도록 구성합니다.

  • 이후 많아진 트래픽에 의해 서버가 더 필요해질 때 upstream에 WAS 서버 정보만 추가하여 손쉽게 Scale Out이 가능합니다.


🔖참고