새소식

Java

[Spring] 성능 테스트 ? Locust로! with Docker

  • -
728x90
선착순 쿠폰 서비스를 기획, 구현 중이다. 하지만 혼자서 접속을 해서 동시 접속자의 상황을 재연하기에는 무리가 있다. 마우스를 잡은 손은 하나니까! 그렇기에 고민하던 중, Locust 에 대해 알게 되었고 동시 접속을 테스트하기에 적합할 뿐만 아니라 성능에 대한 테스트도 가능하다는 것을 알게 되었다. 지금부터 알아보자.

 

 

Locust는 Python으로 작성된 오픈소스 부하테스트 도구이다. Locsut를 사용하면 분산 시스템에서 여러 사용자를 시뮬레이션하여 웹 애플리케이션의 성능을 측정할 수 있다. 또한 매우 사용하기 쉽고 확장성이 뛰어나며, 사용자 시나리오를 코드로 작성할 수 있어 유연성이 높고, 대시보드를 통해 실시간으로 테스트 결과를 모니터링 할 수 있어 테스트 중에 성능 이슈를 발견하고 조치할 수 있다.

 

Locust.io

An open source load testing tool. Define user behaviour with Python code, and swarm your system with millions of simultaneous users.

locust.io

 

docker-compose 를 이용해 구현해 보고자 했다. worker 는 Locust 테스트를 수행하는 역할을 담당하며, master는 Locust 웹 인터페이스를 제공하고, worker에서 수행한 결과를 수집하여 테스트 결과를 종합하고, 그 결과를 웹 인터페이스를 통해 제공한다.

 

Locust with Docker-compose 

load-test 라는 디렉토리를 형성해 그 안에 구성을 해보겠다. 먼저 테스트 파일을 생성한다. locust 는 python 기반의 오픈소스이기 때문에 python 으로 작성해야 한다.

[locustfile-hello.py]
from locust import task, FastHttpUser

class HelloWorld(FastHttpUser):
    connection_timeout = 10.0
    network_timeout = 10.0

    @task
    def hello(self):
        self.client.get("/hello")
        
..
..

[HelloController]
@RestController
public class HelloController {

    // 부하 테스트
    @GetMapping("/hello")
    public String hello() {
        return "hello!";
    }
}

 

FastHttpUser는 Locust의 사용자 모델 중 하나로, 더 빠르고 경량화된 HTTP 클라이언트를 사용하는 것이 특징이다. 

connection_timeout 은 클라이언트가 서버에 연결을 시도할 때 최대 대기 시간을 의미하며,  network_timeout 은 클라이언트가 서버로부터 응답을 받기 위해 대기하는 최대 시간을 의미한다. 또한 task 데코레이터를 사용하여 다음 메서드를 Locust 작업으로 등록한다.

docker-compose 아키텍처

# Docker Compose 파일 버전, 버전 3.7을 사용
version: '3.7'

# 이 파일에서 정의하는 서비스의 목록
services: 
  # 마스터 서비스
  master:  
  	# 사용할 이미지는 locustio/locust
    image: locustio/locust  
    ports:
      # 호스트의 8089 포트와 컨테이너의 8089 포트를 연결 (Locust의 웹 인터페이스 포트)
      - "8089:8089"  
    volumes:
      # 현재 디렉토리(.)를 컨테이너의 /mnt/locust 경로에 마운트 (Locust 스크립트 포함)
      - ./:/mnt/locust 
    command: -f /mnt/locust/locustfile-hello.py --master -H http://host.docker.internal:8080
      # 컨테이너가 시작될 때 실행할 커맨드
      # locustfile-hello.py 파일을 사용, 마스터 모드로 실행, 테스트 대상 호스트는 host.docker.internal:8080

  # 워커 서비스
  worker:  
    # 마찬가지로 locustio/locust 이미지 사용
    image: locustio/locust  
    volumes:
      # 마스터와 동일하게 현재 디렉토리를 컨테이너에 마운트
      - ./:/mnt/locust  
    command: -f /mnt/locust/locustfile-hello.py --worker --master-host master
      # 컨테이너가 시작될 때 실행할 커맨드
      # locustfile-hello.py 파일을 사용, 워커 모드로 실행, 마스터 호스트의 이름을 'master'로 지정 (Docker Compose는 서비스 이름을 호스트 이름으로 사용)

 

docker-compose 에 더욱 익숙해지고 locust 에 대한 내용을 깊이 이해하고 싶어 자세한 내용을 모두 주석으로 달아두었다.

 

여기까지 했으면 모든 준비는 끝났다. 도커를 생성하고 바로 테스트를 진행하자!

 

✅ Locust Connect

docker-compose 를 아래의 명령어로 실행하면 load-test 에 master 와 worker 가 정상적으로 실행된 것을 확인할 수 있다.

docker-compose up -d

생성된 컨테이너

 

그 후에 localhost 의 8089 포트로 접속하면 아래와 같은 페이지를 확인할 수 있다. 이 페이지를 통해  command 에 작성된 파일을 기반으로 docker locust 를 호스팅하고 그에 대한 테스트를 진행한다. 

 

Locust 웹 메인

🔻Number of users

- 생성할 가상 사용자의 최대 수

 

🔻Ramp up

- 초당 생성할 가상 사용자의 수

 

🔻Host 

요청받을 대상 주소

 

나는 Number of Users 의 수를 1,000 으로 하고, Ramp up 의 수를 100으로 설정했다. 즉, 초당 100명씩 최대 1,000명의 가상 사용자를 대상으로 테스트를 진행하기로 했다. 

 

하지만 MySQL 에 CPU 가 7,80% 까지 올라가고 정상적인 테스트가 진행되지 않은 것으로 보였다. 이게 정상적인 테스트라고 볼 수 있는가 ? 

 

이는 한대의 worker 로 초당 100명의 접속을 감당하기에 무리인 것으로 보여, worker 의 수를 증가시켜주기로 했다.

 

docker-compose up -d --scale worker=3

 

Docker 와 Locust 내부, workder 가 3대로 증가한 모습

docker
Locust

 

이를 통해 MySQL 의 부하를 해결하고 정상적인 테스트 환경을 구축할 수 있었다.

 

*️⃣글을 마치며

 

이번 글을 통해 서버 성능 테스트, 스트레스 테스트의 맛을 본 것 같다. 이번 글을 기반으로 좀 더 다양한 테스트를 진행하며 습득하는 지식에 보람을 느끼며 개발의 재미를 느껴가고 있다. 다음 포스팅엔 실제로 선착순 기능에 대한 테스트를 다르며 생기는 트러블 슈팅에 대한 과정을 담아보겠다 : )

728x90
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.