서버가 감당하기 힘든만큼의 요청이 오게되면 어떻게 대처해야할까?
가장 쉬운 방법은 더 좋은 서버를 사용하는 것이다.
하지만, 우리는 돈이 썩어나지 않기에, 서버를 수평확장하는 방식을 고려해야만 한다.
그렇다면 그냥 수평확장만 하면 되는가?
그 확장된 서버들과 기존 서버들에 요청이 골고루 분산되도록 만들어야한다.
이제 프로젝트에 WAS scale out 및 nginx를 이용한 load balacing을 도입해보자.
일부만 첨부
upstream springboot {
server springboot:8080;
}
server{
listen 80;
location / {
proxy_pass http://springboot;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Docker-compose에서 서비스명으로 사용하고 있는 springboot 이 이름은 내부적으로 실행 중인 모든 관련 컨테이너들을 가리킬 수 있기 때문이다.
Docker embedded DNS server가 이를 처리해준다.
따라서, nginx.conf 파일에 별도로 모든 컨테이너를 명시하지 않아도, 모든 springboot 컨테이너들은 같은 서비스로 간주되어 요청을 수신할 수 있으며
서버 개수가 늘거나 줄어도 추가로 .conf 파일을 수정하지 않을 수 있다.
default 값은 round robin 방식이다.
라운드 로빈 알고리즘은 서버 목록을 순환하면서 각 서버에 차례대로 요청을 할당하는 방식으로 동작한다.
Nginx에서는 많은 알고리즘들을 지원하고, 또 수많은 기능들을 제공하고 있으니 이를 잘 찾아보고 적절히 적용하면 좋을 것 같다.
docker-compose up -d --scale springboot=3
docker-compose up -d --scale springboot=1 등 명령어를 쳐보면서 로드밸런싱이 잘 동작하는지 확인해보던중,,


기존에 떠있던 컨테이너로만 요청이 가는 문제가 발생했다.
그렇다면 왜 이런 상황이 생긴걸까?
Nginx가 동적으로 새로 실행된 컨테이너들을 파악할 수 없다고 한다.
즉, Nginx를 재실행 시키거나 클러스터 기반의 오케스트레이션을 수행해야한다.
나는 springboot 서버 scale out시, nginx 컨테이너까지 재실행 시켜보겠다.
아래와같이 스크립트문을 작성하여 컨테이너 수를 파라미터로 전달받으면서 scale out 하고, 자동으로 nginx를 재실행 시키도록 하였다.
#!/bin/bash
# 파라미터에서 인스턴스 수 확인
if [ -z "$1" ]; then
echo "Usage: $0 <number_of_instances>"
exit 1
fi
NUM_INSTANCES=$1
# docker-compose를 사용하여 Spring Boot 서비스를 스케일
echo "Scaling Spring Boot to $NUM_INSTANCES instances..."
docker-compose up -d --scale springboot=$NUM_INSTANCES
# Nginx 컨테이너 재시작
echo "Restarting Nginx..."
docker-compose restart nginx
echo "Operation completed."
부하분산이 잘 동작하는지 확인하기 위해서 서버에서 요청 처리시 log를 남기도록 하였다.
springboot-1: 2700개 요청 동작

springboot-2: 2695개 요청 동작

springboot-3: 2694개 요청 동작

위 결과와 같이 부하 분산이 잘 이루어지고 있음을 확인할 수 있다.