Nginx로 로드밸런싱을 해보기 위해 3개의 인스턴스를 생성하려고 한다.
클라이언트가 Nginx 서버로 요청을 보내면, Nginx 서버가 백엔드 서버1과 백엔드 서버2를 번갈아가면서 요청을 보내도록 로드밸런싱해보자!
세 개의 서버 모두 t4g.small
Ubuntu 22.04 LTS 8GiB로 생성했다. (이 때 아키텍처를 Arm으로 하면 t4g.small
을 무료로 제공해줘서 선택했다.)
로드밸런싱이 잘 되는지 확인해보기 위해 테스트용 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파일을 백엔드 서버 인스턴스로 복사해보자.
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를 설치해보자.
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모듈은 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;
}
추가적인 설정이 궁금하다면 해당링크를 참고하자.
Nginx에서 리버스 프록시를 설정하기 위해 사용되는 키워드로, upstream 서버 집합의 그룹명을 입력하면 해당 upstream모듈의 서버들로 요청을 보낸다. (예시의 경우 upstream 키워드 뒤에 붙여진 samplecluster
가 서버 집합 그룹명이다.)
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로 지정할 수 있는지 몰랐는데 너무 신기하다!!!