Nginx 로드밸런싱

hongo·2023년 8월 25일
2

EC2 인스턴스 생성

Nginx로 로드밸런싱을 해보기 위해 3개의 인스턴스를 생성하려고 한다.

  • Nginx 서버
  • 백엔드 서버1
  • 백엔드 서버2

클라이언트가 Nginx 서버로 요청을 보내면, Nginx 서버가 백엔드 서버1과 백엔드 서버2를 번갈아가면서 요청을 보내도록 로드밸런싱해보자!

세 개의 서버 모두 t4g.small Ubuntu 22.04 LTS 8GiB로 생성했다. (이 때 아키텍처를 Arm으로 하면 t4g.small을 무료로 제공해줘서 선택했다.)

테스트용 WAS 생성

로드밸런싱이 잘 되는지 확인해보기 위해 테스트용 WAS를 만들어보자.

Spring boot 애플리케이션에 하나의 컨트롤러를 생성했다.

@RestController
public class ServerController {
    private final int serverNumber;
    private int count = 0;

    private ServerController(@Value("${server-number}") final int serverNumber) {
        this.serverNumber = serverNumber;
    }

    @GetMapping
    public ResponseEntity<Map<String, Integer>> count() {
        count ++;
        Map<String, Integer> data = new HashMap<>();
        data.put("Server Number", serverNumber);
        data.put("Visiting Count", count);
        return ResponseEntity.ok(data);
    }
}

몇 번째 서버인지를 볼 수 있게 서버 번호와, 요청을 받은 횟수를 보여주는 API를 만들었다.

spring:
  config:
    activate:
      on-profile: server1

server-number: 1

---

spring:
  config:
    activate:
      on-profile: server2

server-number: 2

서버별로 자신의 번호를 가질 수 있게 application.yml 프로필을 나누었다.

백엔드 서버 실행

애플리케이션을 만들었으면, 백엔드 서버에서 애플리케이션을 실행해보자!

jar파일을 인스턴스로 복사

백엔드 서버에서 애플리케이션을 실행할 수 있게, jar파일을 백엔드 서버 인스턴스로 복사해보자.

scp 명령어를 사용하면 파일을 복사할 수 있다.

우선 터미널에 ./gradlew bootJar 명령어를 쳐서 jar파일을 생성하자.

프로젝트의 build/libs 경로 하위에 jar파일이 생성된다.

build/libs 경로로 이동해서 scp 명령어를 사용해보자.

scp {파일이름}.jar root@서버IP:{복사한파일이름}.jar의 형태로 입력하면 된다.

예시 : scp load-balancer-test-0.0.1-SNAPSHOT.jar ubuntu@111.111.111.111:server.jar

pem키로 인증이 필요한 경우엔 -i옵션과 키가 위치한 경로를 덧붙여주면 된다.

예시 : scp -i /c/Users/sec/Downloads/test.pem load-balancer-test-0.0.1-SNAPSHOT.jar ubuntu@111.111.111.111:server.jar

서버 실행

이제 ssh 명령어를 사용해 백엔드 서버에 접속해보자.

예시 : ssh -i /c/Users/sec/Downloads/test.pem ubuntu@111.111.111.111

서버에 접속하면 scp로 옮긴 jar파일을 볼 수 있다. jar파일을 시작하기 전에 sudo apt-get을 업데이트 하고 자바를 설치하는 것을 잊지말자!

sudo apt-get update

sudo apt install openjdk-17-jdk -y

jar파일이 있는 경로에서 nohup을 사용해 백그라운드에서 애플리케이션을 실행해보자. 이 때 서버별로 어떤 application.yml 프로필을 적용해줄 것인지 명시해주는 것을 잊지말자.

예시 : nohup java -jar Dspring.profiles.active=server1 server.jar &

위 방식으로 백엔드 서버1과 백엔드 서버2를 실행시키고 8080포트로 접속해서 서버가 잘 실행됐는 지를 확인해보자.

Nginx 서버 설정

백엔드 서버를 실행시켰으니, Nginx 서버를 실행시킬 차례이다.

Nginx서버에 접속해서 Nginx를 설치해보자.

sudo apt-get update

sudo apt-get install nginx -y

서버의 public ip주소에 접속했을 때 아래와 같은 화면이 뜨면 Nginx가 잘 설치된 것이다.

로드밸런싱을 위한 설정 추가

이제 Nginx로 로드밸런싱을 하기 위해 설정을 추가해야한다.

서버의 root에서 etc/nginx 경로로 들어가면 nginx.conf라는 파일이 생겼을 것이다. 해당 파일에 Nginx에 대한 설정을 추가할 수 있다.

(nginx.conf 파일이 읽기 전용 모드라면 chmod를 사용해 쓰기 권한을 부여한다.)

http {
    upstream samplecluster {
        server 111.111.111.111:8080; # 백엔드 서버1의 IP주소
        server 222.222.222.222:8080; # 백엔드 서버2의 IP주소
    }

    server {
        listen 80;

        location / {
            proxy_pass http://samplecluster; # upstream 옆의 이름을 등록
        }
    }

	...
}

...

upstream

upstream모듈은 Nginx가 받은 요청을 어떤 서버에게 돌려줄 지를 지정하는 블록으로 로드밸런싱할 서버들을 설정할 수 있다. server 키워드와 함께 로드밸런싱할 서버들을 적어주면 된다.

로드밸런싱 알고리즘 전략도 지정할 수 있다. 디폴트 전략은 라운드 로빈이다.

예시 :

upstream samplecluster {
  least_conn; # 연결된 횟수가 가장 적은 서버로 연결되는 알고리즘
  server 111.111.111.111:8080;
  server 222.222.222.222:8080;
}

또, 각 server의 옆에 가중치등 설정을 덧붙일수도 있다.

예시 :

upstream backend {
  server 111.111.111:8080 weight=2;
  server 222.222.222:8080;
  server 333.333.333:8080;
}

추가적인 설정이 궁금하다면 해당링크를 참고하자.

proxy_pass

Nginx에서 리버스 프록시를 설정하기 위해 사용되는 키워드로, upstream 서버 집합의 그룹명을 입력하면 해당 upstream모듈의 서버들로 요청을 보낸다. (예시의 경우 upstream 키워드 뒤에 붙여진 samplecluster가 서버 집합 그룹명이다.)

Nginx 재실행

nginx.conf를 수정했다면 변경한 설정이 다시 적용되도록 Nginx를 reload해줘야한다.

sudo nginx -s reload 를 사용해 Nginx를 재실행한다.

upstream의 서버 그룹명 이름이 127.0.0.1:8080이고, Nginx가 있는 서버의 8080포트에 WAS가 실행중일 때 proxy_pass가 upstream안의 서버와 내부 8080포트 중 어떤 것을 더 우선해서 연결해줄지가 궁금해서 시도해봤는데, upstream 은 127.0.0.1:8080 형태의 이름으로 지정했을 때 Nginx가 아예 프록시 연결을 해주지 않았다... 에러는 안나는데 502가 뜨다니...

결과

{"Visiting Count":235,"Server Number":1}

{"Visiting Count":234,"Server Number":2}

{"Visiting Count":236,"Server Number":1}

{"Visiting Count":235,"Server Number":2}

{"Visiting Count":237,"Server Number":1}

{"Visiting Count":236,"Server Number":2}

Nginx서버의 80포트로 접속하면, 백엔드 서버1과 백엔드 서버2를 번갈아가면서 요청하는 것을 볼 수 있다!

upstream 모듈로 요청을 보낼 서버를 지정하고 바로 proxy_pass로 지정할 수 있는지 몰랐는데 너무 신기하다!!!

참고

0개의 댓글