부하 테스트 LOCUST 구축
LOCUST ?
로커스트는 HTTP 및 기타 프로토콜을 위한 오픈 소스 성능/부하 테스트 도구로 사용하기 편하며, 스크립트로 작성 및 확장 가능하다.
테스트 시나리오를 파이썬 코드로 작성이 가능하다.
분산환경에서 확장이 가능하다. (많은 부하를 테스트 할때 부하를 발생시키는 서버를 여러대로 해서 테스트 가능)
웹 기반 UI를 제공해서 테스트 결과나 진행 사항을 차트나 표로 볼 수 있다.
구현 방법
- /coupon-management-system/load-test/docker-compose.yml로 구성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3.7'
services:
master:
image: locustio/locust
ports:
- "8089:8089"
volumes:
- ./:/mnt/locust
command: -f /mnt/locust/locustfile-hello.py --master -H http://host.docker.internal:8080
worker:
image: locustio/locust
volumes:
- ./:/mnt/locust
command: -f /mnt/locust/locustfile-hello.py --worker --master-host master
서비스
Locust 컨테이너를 실행하는 두 개의 서비스가 있다.
1. master
image: locustio/locust: 분산 로드 테스트를 위한 공식 Locust 이미지를 사용함.ports: - "8089:8089": 컨테이너의 포트 8089를 호스트 머신의 동일한 포트에 노출함. 이를 통해 웹 브라우저에서 Locust 웹 인터페이스에 접근할 수 있다.volumes: - ./:/mnt/locust: 현재 디렉토리(docker-compose.yml 파일이 있는 디렉토리)를 컨테이너 내의/mnt/locust에 연결. 이를 통해 컨테이너는 Locust 테스트 파일에 접근할 수 있다.command: -f /mnt/locust/locustfile-hello.py --master -H http://host.docker.internal:8080:
-f /mnt/locust/locustfile-hello.py- 제공된 Locust 파일을 실행한다.--master- 이 컨테이너를 Locust 클러스터의 마스터 노드로 지정.-H http://host.docker.internal:8080- 로드 테스트의 대상 URL을 설정. (host.docker.internal에 대한 중요한 참고 사항은 아래를 참조.)
2. worker
image: locustio/locust: 마스터와 동일한 Locust 이미지.volumes: - ./:/mnt/locust: Locust 테스트 파일에 대한 접근 권한을 위해 동일한 디렉토리를 연결.command: -f /mnt/locust/locustfile-hello.py --worker --master-host master:
-f /mnt/locust/locustfile-hello.py- 동일한 Locust 파일을 실행.--worker- 이 컨테이너를 작업자 노드로 지정.--master-host master- 작업자가 ‘master’라는 이름의 마스터 노드(master 서비스에서 정의됨)에 연결하도록 지시.
핵심 포인트
- 분산 로드 테스트: 이 설정을 통해 마스터가 조율하는 여러 작업자 노드에서 대규모 부하를 시뮬레이션할 수 있다.
- Locustfile: 현재 디렉토리에
locustfile-hello.py라는 이름의 파일이 있어야 하며, 이 파일은 Locust가 실행할 실제 테스트 케이스를 포함해야 한다.. - UI에 접근: 웹 브라우저에서 http://localhost:8089를 열면 Locust 제어판에 접근할 수 있다.
- host.docker.internal: 이 특정 호스트 이름은 일반적으로 Docker 컨테이너 내에서 호스트 머신에 접근하도록 합니다. 운영 체제에 따라 조정이 필요할 수 있다.
- locustfile-hello.py 생성 부하 테스트 작성
1
2
3
4
5
6
7
8
9
from locust import task, FastHttpUser
class HelloWorld(FastHttpUser):
connetcion_timeout = 10.0
network_timeout = 10.0
@task
def hello(self):
self.client.get("/hello")
Locustfile 분석
임포트
from locust import task, FastHttpUserLocust 라이브러리에서 필수 구성 요소를 가져옴.
task: 함수를 Locust 작업(시뮬레이션된 사용자가 수행하는 작업)으로 표시하는 데코레이터.FastHttpUser: HTTP 사용자 행동을 시뮬레이션하기 위한 전문 클래스.
클래스 정의
class HelloWorld(FastHttpUser):HelloWorld라는 Locust 사용자 클래스를 정의함. 이 클래스는FastHttpUser로부터 동작을 상속받는다.
타임아웃 설정
connection_timeout = 10.0: 대상 서버에 대한 새 연결을 설정할 때 최대 대기 시간(10초)을 설정함.network_timeout = 10.0: 연결이 설정된 후 서버 응답을 기다리는 최대 시간(10초)을 설정함.
작업 정의
@task: 이 데코레이터는hello함수를 Locust 작업으로 지정.def hello(self)::hello라는 작업 함수를 정의함.self인수는 시뮬레이션된 사용자 인스턴스를 나타낸다.self.client.get("/hello"): 작업 내에서 사용자는 대상 서버의/hello엔드포인트에 GET 요청을 한다. 이것은FastHttpUser가 제공하는 내장client객체를 사용하여 수행됨.
요약
이 Locust 파일은 다음과 같은 간단한 사용자 동작을 시뮬레이션함.
- 사용자 인스턴스화: Locust가 시작되면
HelloWorld클래스의 인스턴스를 생성함. 각 인스턴스는 가상 사용자를 나타낸다. - 작업: 각 가상 사용자는
hello작업을 반복적으로 실행한다. - HTTP 요청:
hello작업은 사용자에게 대상 시스템의/hello엔드포인트에 GET 요청을 보내도록 지시한다. - 타임아웃: 연결 및 네트워크 타임아웃은 서버에 문제가 있는 경우 테스트가 무한정 중단되지 않도록 함.
Locust가 이 파일을 사용하는 방법
- Locust 테스트를 실행하면 Locust는 이 파일을 읽고 시뮬레이션된 사용자 동작을 이해함.
- Locust는
HelloWorld사용자의 많은 인스턴스를 생성. - 이러한 가상 사용자는
/hello에 지속적으로 GET 요청을 보내 대상 시스템에 부하를 가한다.
LOCUST 실행
- localhost:8089로 접속하여 로커스트를 실행한다.
Number of Users는 최대 사용자 수를 말한다.
Ramp Up은 초당 증가하는 사용자 부하 사용자 수 이고, Host는 부하를 수행할 주소이다.
테스트 전 부하 서버를 늘리기 위해(부하 서버 분산 환경 설정) 아래와 같이 도커 컴포즈의 워커수를 스케일 해준다.
1
$ docker-compose up -d --scale worker=3
- 부하 워커가 3개가 되면서 총 1000명의 유저에 대해 3/1로 분담하여 부하를 주고 있다. (단일 워커 일때 cpu가 100이상 사용되어 제대로 된 부하를 주지 못한다.)
부하 테스트 결과
- Type : HTTP 메소드
- Name: 호출한 URL
- Requests: URL 호출 요청 횟수
- Fails: URL 호출 후 실패 횟수
- Median(ms): 응답에 대한 중앙 시간 값
- 95%lie (ms): 95% 하위 느린 응답 시간 값
- Average (ms): 평균 응답 시간 값
- Min (ms): 최소 응답 시간 값
- Max (ms): 최대 응답 시간 값
- Current RPS: 현재 초당 몇건의 요청을 처리하는지 나타내는 지표
- Current Failures/s: 현재 초당 실패 횟수
차트 지표
위 내용을 차트로 보게되면 시간에 따른 RPS와 실패 내역을 알수 있고, 평균 응답 시간 값과 95% 하위 응답 시간 값 마지막으로 시간에 따른 사용자 수를 한 눈에 볼수 있다.
Locust Report
- 부하 테스트 결과를 리포트 형식으로 다운로드 가능하다.
- 간단히 보면 언제 부터 언제까지 실행한 결과이며, 어떤 호스트를 타켓으로 했는지, 스크립트는 어떤 스크립트를 사용하였는지를 알려준다.
- 또한 관련된 statistics 정보와 차트를 보여준다.
번외
- 만약 요청한 target의 웹서버에서 초당 처리량을 제한을 둔다면 어떻게 될까?
- 예를 들어 초당 요청에 대해 threads.sleep(500) 즉, 초당 2건의 요청을 처리하도록 제한을 둔다면
- 아래는 총 사용자 5000명에 대해 초당 100명의 사용자가 증가할때 그래프이다.
- 그래프를 보면 사용자가 증가하면서 어느순간 실패가 증가하면서 응답시간이 10000ms로 증가하는 걸 볼수 있다. 즉 사용자가 증가함에 따라 타임아웃이 발생하면서 서버가 터진걸 볼 수 있다.
- 따라서 사용자 수에 따라 처리량을 제안하는 방법은 위험하고 대규모 시스템에서는 사용자 대비 처리량을 증가 시키는 방법에 대한 고민이 필요하다.