마이의 개발 블로그

[Network] Docker Compose와 Nginx를 이용한 수평 스케일(scale-out)과 로드 밸런싱(Load Balancing) 본문

개발지식/인프라

[Network] Docker Compose와 Nginx를 이용한 수평 스케일(scale-out)과 로드 밸런싱(Load Balancing)

개발자마이 2024. 12. 10. 10:46
반응형

배경

납품한 솔루션 WAS의 응답이 피크 시간대에 느려지는 현상이 관찰되었습니다. 초당 약 600개 이상의 페이지 요청이 지속적으로 발생함을 모니터링할 수 있었는데 이는 기존 고객사들 대비 많은 처리량을 요구하다보니 별도의 조치가 필요했습니다. 이에 따라 제한된 자원 내에서 수평 스케일(scale-out)에 대한 부하 테스트를 수행하여 적당한 타협점을 도출해낼 수 있었는데, 그 과정과 결과를 공유하고자 합니다. 로드밸런싱은 도커와 Nginx를 이용하여 수행했습니다.

테스트 수행 방식

- JMeter 이용

- OS에서 도커 자원 제한: 8코어 16GB 메모리 (다수 컨테이너가 공유함)

- 가장 많은 부하가 걸리는 WAS의 API에 대해 초당 요청 수를 증가시켜가며 평균, 최대 응답시간 측정

테스트 결과

*결과표의 'CPU(코어)' 수는 솔루션의 여러 컨테이너가 함께 사용하는 총 코어 수를 의미합니다.

*부하테스트의 대상이 되는 단일 WAS의 최대 사용 코어 수는 workers * WAS 도커 인스턴스 수입니다.

*workers: uvicorn의 workers 인자를 의미합니다. 서버의 동시 요청 처리를 위한 프로세서 개수를 지정하는 옵션입니다.

 

- workers는 도커 인스턴스당 1개로 유지할 때 가장 높은 효율을 보였습니다. 코어 수보다 workers를 높일 경우 유의미한 성능 향상을 관찰할 수 없었습니다. 이는 테스트 대상 API의 비즈니스 로직이 CPU집약적인 동작을 포함하여 단일 코어를 하나의 worker로 사용하는 것이 효율적이기 때문인 것으로 추측됩니다.

- 동일한 환경에서 로드밸런싱을 수행했을 때가 아닐 때보다 더 빠른 평균응답시간을 보여주었습니다.

- 로드밸런싱을 수행할 때 특정 수준까지 인스턴스 개수가 늘어날 수록 최대지연시간이 줄어들었습니다.

- 인스턴스 개수가 늘어나더라도 평균 지연시간이 더이상 줄어들지 않는 지점이 관찰되었으나 제한된 자원으로 인해 해당 결과는 적용할 수 없었습니다.

 

-> 인스턴스 4개, 인스턴스당 1코어 할당

Docker Compose와 Nginx를 이용한 로드밸런싱 예제

1. Docker Compose 설정

version: '3'
services:
  test-server1:
    image: <이미지>
    container_name: <컨테이너1>
    restart: always
    command: uvicorn src.server.main:app --host=0.0.0.0 --port=8000 --timeout-keep-alive=60
    working_dir: /app

  test-server2:
    image: <이미지>
    container_name: <컨테이너2>
    restart: always
    command: uvicorn src.server.main:app --host=0.0.0.0 --port=8000 --timeout-keep-alive=60
    working_dir: /app

  test-server3:
    image: <이미지>
    container_name: <컨테이너3>
    restart: always
    command: uvicorn src.server.main:app --host=0.0.0.0 --port=8000 --timeout-keep-alive=60
    working_dir: /app

  test-server4:
    image: <이미지>
    container_name: <컨테이너4>
    restart: always
    command: uvicorn src.server.main:app --host=0.0.0.0 --port=8000 --timeout-keep-alive=60
    working_dir: /app

2. Nginx 설정

  upstream test-server {
    server test-server1:8000;
    server test-server2:8000;
    server test-server3:8000;
    server test-server4:8000;
  }

  server {
    listen 80;

    location / {
      proxy_pass http://test-server/;
    }
  }

3. 설명

- Nginx와 WAS 둘 다 도커 컨테이너로 동일한 네트워크에서 동작하게끔 구성되어있습니다. 그렇기 때문에 Nginx에서 WAS 컨테이너를 이름(test-server1~4)으로 직접 호출 가능합니다.

- Docker Compose에서 동일한 WAS 이미지를 사용하여 4개의 컨테이너를 각각 생성합니다. 이 때, 외부노출 포트, 서비스명, 컨테이너명 등이 겹치지 않아야 합니다.

- Nginx에서는 upstream 블록을 사용하여 test-server1~4를 test-server라는 하나의 이름으로 묶어줍니다. 그리고 원하는 위치에 test-server를 호출하게끔 설정합니다.

- Nginx에서는 기본 설정으로 라운드 로빈(Round Robin) 방식의 로드밸런싱을 수행합니다.

Note

오토스케일링이 필요한 경우, 모니터링 및 인스턴스 증감을 조절하는 스크립트를 이용하거나 쿠버네티스(Kubernetes), 도커 스웜(Docker Swarm) 등의 오케스트레이션 툴을 사용할 수 있습니다.

반응형
Comments