현재 우리 서버의 구조이다. Docker Image
를 Docker-compose
파일로 컨테이너화 한다.
nginx
는 80 port
, 443 port
로 들어온 요청을 컨테이너가 실행되는 3000 port
로 reverse-proxy
시킨다.
version: '3'
services:
egusajo-0:
image: ghcr.io/inha-commit/egusajo-nest:latest
container_name: egusajo-0
ports:
- "3000:3000"
restart: always
networks:
- egusajo_network
networks:
egusajo_network:
external: true
먼저 현재 우리의 서버를 생성하는 docker-compose 파일이다. docker-compose 파일을 수정해서 container로 늘려주자.
version: '3'
services:
egusajo-0:
image: ghcr.io/inha-commit/egusajo-nest:latest
container_name: egusajo-0
ports:
- "3000:3000"
restart: always
networks:
- egusajo_network
egusajo-1:
image: ghcr.io/inha-commit/egusajo-nest:latest
container_name: egusajo-1
ports:
- "3001:3000"
restart: always
networks:
- egusajo_network
egusajo-2:
image: ghcr.io/inha-commit/egusajo-nest:latest
container_name: egusajo-2
ports:
- "3002:3000"
restart: always
networks:
- egusajo_network
egusajo-3:
image: ghcr.io/inha-commit/egusajo-nest:latest
container_name: egusajo-3
ports:
- "3003:3000"
restart: always
networks:
- egusajo_network
egusajo-4:
image: ghcr.io/inha-commit/egusajo-nest:latest
container_name: egusajo-4
ports:
- "3004:3000"
restart: always
networks:
- egusajo_network
networks:
egusajo_network:
external: true
이렇게 docker-compose
파일에 설정을 추가하여 컨테이너를 다섯개로 늘려 준다.
5개의 컨테이너가 실행되고 있는 것을 확인할 수 있다.
늘려주면 이렇게 되었다. 컨테이너는 다섯개가 되었지만(그림에선 4개만 그림) nginx
는 3000 port
로만 요청을 전달한다. 이제 nginx 파일을 수정해서 요청을 분산하도록 하자.
server {
server_name [your_server_domain];
location / {
proxy_pass http://127.0.0.1:3000;
}
listen 443 ssl; # managed by Certbot
...
}
server {
if ($host = [your_server_domain]) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name [your_server_domain];
return 404;
}
기존의 nginx 설정 파일이다. domain에 맞는 http요청이 들어오면 nginx가 reverse-proxy시켜주어 우리의 컨테이너에게 정보를 전달해준다.
upstream servers {
least_conn;
server 127.0.0.1:3000 weight=10 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3001 weight=10 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3002 weight=10 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3003 weight=10 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3004 weight=10 max_fails=3 fail_timeout=30s;
}
server {
server_name your_server_domain];
location / {
proxy_pass http://servers;
}
listen 443 ssl; # managed by Certbot
...
}
...
위 옵션을 추가해주자.
least_conn
은 Nginx에서 사용되는 업스트림 서버의 로드 밸런싱 방식 중 하나이다. 이 옵션은 연결 요청을 처리할 때 현재 가장 적은 활성 연결 수를 가진 서버에 우선적으로 연결을 전달한다.
least_conn
을 사용하면 현재 연결 상태를 고려하여 트래픽을 분산시키기 때문에 서버 간의 부하를 균등하게 분배할 수 있다. 나는 이 방식이 서버에 필요하여 least_conn
방식을 사용했다.
다른 로드 밸런싱 방식에는 round-robin
과 ip_hash
등이 있다.
Round Robin (라운드 로빈):
라운드 로빈 방식은 연속된 요청을 순차적으로 다음 서버로 배분한다. 맨 처음 요청은 첫 번째 서버에, 다음 요청은 두 번째 서버에, 그 다음은 세 번째 서버에 순서대로 전달된다. 이 패턴이 반복된다.
모든 서버에 대해 균등하게 트래픽을 분산시키지, 서버 간의 상태를 고려하지 않으므로, 각 서버의 부하나 성능 차이를 고려하지 않는다.
IP Hash (IP 해시):
IP 해시 방식은 클라이언트의 IP 주소를 기반으로 요청을 서버로 분배한다. 클라이언트의 IP 주소에 대한 해시값을 계산하고, 그 해시값을 이용하여 어느 서버로 요청을 보낼지 결정한다. 이를 통해 특정 클라이언트가 항상 동일한 서버로 요청을 보낼 수 있다.
특정 세션에 대해 항상 동일한 서버로 요청을 보내기 때문에 세션 유지가 필요한 경우에 유용하다.
하지만 서버가 추가되거나 제거될 때 해시값이 변경되어 새로운 서버로 연결되는 문제가 발생할 수 있다. 또한, 서버 간 부하 차이를 고려하지 않는다.
이제 우리 서버는 이런 형식이 되었다.
요창을 20개 보냈을때 한 서버에 5개만 도달한 것을 확인할 수 있다. 성공!