NCP에서 Nginx를 이용하여 로드밸런싱 구현하기

xeonu·2023년 1월 29일
0

Infra

목록 보기
3/4

프로젝트 링크: https://github.com/f-lab-edu/Soccer-Friend

지난 포스팅에서 대규모 트래픽을 감당하기 위해 Scale Up방식을 통해 서버를 확장하기로 했다. 여러대의 서버로 트래픽을 분산시키기 위해서 로드밸런서를 구축해야한다. NCP와 AWS를 포함한 클라우드 서비스에서는 자체적으로 로드밸런서 서비스를 제공한다. 실제로 이들을 사용하면 편하게 로드밸런싱 환경을 구축할 수 있지만 클라우드 서비스에 구애받지 않는 웹서버를 구축하여 로드밸런싱을 구현해보도록 하자.

로드밸런싱이란

로드밸런싱이란 사용자의 요청을 다수의 서버에 분산시키는 것을 의미한다. 특정 URL에 접속하면 특정 서버로만 요청을 보낼 수도 있고 단순히 부하분산이 목적이라면 적절한 로드밸런싱 알고리즘을 이용해 균등하게 분산시킬 수 있다. 우리는 Nginx를 이용하여 로드밸런싱을 구현할 것이고 Nginx에서 제공하는 로드밸런싱 알고리즘에 대해 공식문서를 통해 알아볼 것이다.

Web Server와 WAS

Web Server

웹 서버는 HTTP 프로토콜을 통해 클라이언트 측에서 요청이 오면 정적컨텐츠를 제공하는 서버이다. 여기서 정적 컨텐츠는 HTML, 이미지, 파일 과 같은 다른 복잡한 비즈니스 로직 처리가 필요하지 않은 단순한 컨텐츠이다. 만약 웹서버가 정적 컨텐츠가 아닌 동적 컨텐츠를 요청받으면 해당 작업을 WAS에 전달하고 응답받아 WAS에서 처리한 결과물을 클라이언트로 전송해준다. 이런 웹서버에는 Apache와 Nginx가 있고 이 프로젝트에서는 Nginx를 사용하고자 한다.

WAS(Web Application Server)

WAS는 단순한 컨텐츠 전송 목적이 아닌 DB 조회와 같은 복잡한 비즈니스 로직을 수행하는 동적 컨텐츠를 제공하는 서버이다. WAS를 여러대 두어 서로 다른 비즈니스 로직을 처리하고 개발의 유지보수성을 높여주는 MSA 환경을 구축할 수도 있다. 이 프로젝트는 스프링 부트를 기반으로 서버프로그램을 제작하므로 기본적으로 TomCat을 WAS로 사용한다.

Web Server와 WAS로 구축한 아키텍처

Web Server와 WAS를 분리하여 인프라 아키텍처를 구축하면 다음과 같다. 사용자는 Web Server로 요청을 보내고 Web Server는 WAS에 해당 요청을 보낸 후 비즈니스 로직을 처리한 결과물을 다시 Web Server로 전송한다. Web Server는 다시 사용자로 부터 응답을 보내어 통신하는 구조이다. 이 프로젝트는 저러한 WAS를 3대 두어 트래픽을 분산시킨다. 여기서 Nginx는 사용자와 직접 통신하는 Web Server이고 TomCat은 WAS이다.

Apache에서 Nginx로

과거에는 Apache HTTP Server(이하 Apache)를 이용하여 웹서버를 구축했다. 하나의 요청에 하나의 프로세스가 대응하는 blocking I/O 방식으로 요청을 처리했고 이를 위해 fork와 kill을 통해 적절한 프로세스 개수를 조절한다. 하지만 세월이 흐르고 기술이 발전하면서 동시접속하는 사용자의 수가 늘어나고 처리해야할 데이터의 크기도 커진다. blocking 방식으로 모든 사용자의 요청을 처리하기 위해서 필요한 프로세스의 개수가 너무 많아진다. 프로세스를 생성할 때마다 메모리의 공간을 요구하고 결국 동시처리 성능이 떨어지게된다.

이를 개선하기 위해 Nginx는 비동기 이벤트 기반 구조를 통해 너무 많은 프로세스를 생성하지 않아도 다수의 요청을 처리할 수 있다. 이전 작업이 처리될 때까지 무한정 대기하는 것이 아닌 큐에 작업들을 저장해 두고 이전 작업이 끝날 때 마다 큐에서 가져와 작업을 처리하는 방식이다. 이를 통해 Apache처럼 불필요하게 프로세스를 많이 생성할 필요도 없고 낭비되는 프로세스 자원도 줄어든다.

이 프로젝트에서는 웹서버가 로드밸런서의 역할만 수행하기 때문에 Nginx로 웹서버로 두어 로드밸런서를 구축하고자한다. 추가적으로 WebServer에 대해 알아보았는데 LiteSpeed라는 제품도 성능이 좋아보여서 기회가 되면 알아보고싶다.

NCP에서 Nginx 서버 구축하기

3대의 WAS 구축

로드밸런서를 구축하기 전에 NCP에 3개의 서버를 생성하여 동일한 스프링 부트 프로젝트를 배포했다. 스프링 부트는 실행시 TomCat을 이용하여 외부와 통신합니다. 즉 이 3개의 서버는 WAS의 역할을 한다. 각 서버의 공인 IP로 외부에서 접속하면 서버의 기능들을 이용할 수 있다. 이제 이 3대의 서버로 트래픽을 분산시켜 줄 Nginx 서버를 구축해보겠다.

Ubuntu Server 생성하며 Nginx 설치하기

Compact 사양의 ubuntu 서버를 하나 생성해주고 콘솔에 접속해준다. 필자는 Mac 터미널과 SSH 접속을 했다.
$ sudo apt update
$ sudo atp upgrade

apt 패키지 목록을 업데이트한다.

$ sudo apt install nginx

nginx를 설치한다.

지금 상태로 Nginx를 실행하면 오류가 발생한다. 그 이유는 Nginx는 기본적으로 80번 포트를 할당받아 외부와 통신하는데 우분투에서 80번 포트는 Apache가 사용하고 있기 때문이다.

 $ netstat -nap | grep 80

위 명령어로 확인해보면 80번 포트를 Apache가 사용중인 것을 확인할 수 있다.

 $ fuser -k -n tcp 80

80번 포트를 사용하는 프로세서를 kill 해줍시다. 물론 정상적으로 Apache의 stop 명령어를 사용하는 것이 권장되지만 운영체제마다 명령어가 다르니 kill 하는 방법으로 대체한다.

$ sudo service start nginx

위 명령어로 Nginx를 실행해준다. 혹시나 오류가 발생한다면

$ sudo service status nginx

해당 명령어로 Nginx의 상태를 확인하고 오류메시지를 확인해서 처리하면 됩니다.

로드밸런싱 경로 설정하기

$ vi etc/nginx/nginx.conf

nginx 설정파일을 vim 에디터로 수정해보자. 이 때는 공식문서를 참고하면 도움이 된다.

다음과 같이 nginx.conf 파일을 수정해주면 된다. 각 키워드에 대한 설명은 공식문서에 자세하게 나와있고 간략하게 설명하고 넘어가자. http 블록은 http와 관련된 설정들을 작성해주면 된다. 대부분의 설정이 http 블록에서 작성된다.

myapp1이라는 upstream 블록을 생성해준다. 여기서 upstream 블록은 Nginx가 요청을 보낼 서버들의 주소를 작성해준다.
server <WAS 공인IP>/<포트번호>; 형식으로 추가해주면된다. 로드밸런싱 알고리즘도 작성해줄 수 있는데 작성해주지 않으면 default로 라운드로빈 알고리즘이 적용된다.

별도로 알고리즘을 작성해주면 ip_hash와 least_conn과 같은 알고리즘도 사용할 수 있다. 유료 라이센스를 구입하면 더 다양한 로드밸런싱 알고리즘을 제공한다.

server 블록은 외부와 통신하기 위한 정보를 작성해주면 됩니다. listen 80;은 80번 포트로 외부에서 접속할 수 있다는 의미이며 location /은 http 요청이 오면 해당 upstream 블록에 존재하는 server로 요청을 보내라는 의미입니다.

nginx의 공인ip의 80번 포트로 접속해보면 정상적으로 WAS와 통신할 수 있음을 확인할 수 있습니다.


이 프로젝트는 모놀리식 아키텍처로 설계되어 모든 사용자의 요청을 아무 WAS에 보내도 상관이 없지만 마이크로서비스 아키텍처로 구현한다면 특정 URL에 따라 해당 비즈니스로직을 처리할 수 있는 WAS로 요청을 보낼 수 있다. 추후에 MSA 아키텍처로 프로젝트를 진행할 기회가 생긴다면 이런 방식으로 트래픽을 분산시켜 유지보수와 트래픽 대응에 유연한 아키텍처를 설계해보고 싶다.

참고 문헌
https://code-lab1.tistory.com/199
https://nginx.org/en/docs/http/load_balancing.html
https://bentist.tistory.com/80

profile
백엔드 개발자가 되기위한 여정

0개의 댓글