3 분 소요

Redis의 메모리 사용량, DB 응답시간 등을 분석하기 위하여 k6를 이용한 성능 테스트를 진행해보려고 한다.

1) 일단 k6를 설치했다. https://grafana.com/docs/k6/latest/set-up/install-k6/ 에 나와있는 방법대로, Linux 명령어를 차례로 입력한다.
로컬은 windows이지만, 테스트 하는 환경을 분리시키기 위해 linux로 설치한다.

2) 로직의 응답이 정확한지 다시한번 확인하기 위해, swagger UI를 켜서 회원가입/로그인/로그아웃을 해본다.
securityConfig.kt랑 requestFilter에서 uri 허용할때 오타를 내서 시간을 많이 잡아먹었다. 다음부턴 조심해야겠다.

Swagger 들어가면 이렇게 뜬다.
swagger

응답이 200/201/200 이면 성공이다.

3) mysql 콘솔로 직접 들어가서 보자.
WSL에 docker exec(도커 실행) -it(명령어 인터렉티브 조작) rainmind_mysql(들어갈 컨테이너 이름) mysql -urainmind(mysql 유저이름이 rainmind) -pxxxxxxxx(비밀번호) rainmind(사용할 데이터베이스의 이름)

redis 콘솔도 가능하다. 동일한 방식으로 docker exec -it rainmind_redis redis-cli를 실행하면 된다. redis-cli는, rainmind_redis 컨테이너 안에서 redis 전용 커맨드라인 도구를 실행하라는 뜻이다.

docker-compose.yaml 파일에서 컨테이너 이름, url, username, pw 등을 설정할 수 있다.

아까 swagger를 통해 생성했던 유저가 mysql db에 잘 들어간 것을 볼 수 있다.
checkdb

이제 로그인 이후 schedule 생성하는 api를 호출해야 한다. 그냥 호출하면 JWT 인증 토큰을 못붙이므로, OpenApiConfig.kt 파일을 별도로 만들어, swagger 에서 토큰을 자동으로 붙이도록 해주었다.

4) k6 스크립트 작성해서 테스트 진행
우선 로그인 1명의 유저에 대해 반복 접근하는 기초적인 스크립트부터 작성 후 실행했다.
login_N_test.js

오 된다.
로그를 한번 해석해보자.

  • http_reqs: 9 = 요청을 9번 했음
  • http_req_failed: 0 = 요청 전부 성공
  • http_req_duration: avg = 121.36ms 평균 수치
  • p(90, 95): 전체 요청 중, 가장 느린 상위 (100-90), (100-95)%의 사용자가 체감한 요청 시간

로그인 + 일정 생성도 같이 해본다.
login_and_schedule_Test.js

잘 되는 것을 확인할 수 있다.

5) 이제 할 것은 서버 실행환경과 스크립트 환경을 분리하는 것이다. + EC2 접속
일반적으로, 서비스를 이용하는 것은 클라이언트(=로컬)고, 서버는 주로 외부(=AWS EC2)이므로 EC2 인스턴스를 생성해야 정확한 테스트가 될 것이다.

이제 EC2 인스턴스를 생성하자.

프리티어로 제공되는 것 중에 RAM이 제일 큰 걸로 선택하고, storage는 20으로 설정했다.
RSA 암호화 키를 발급받고, chmod로 키 권한 user read only로 바꿔주고 ssh -i xxx.pem ubuntu@yyyy.y.y.y로 접속하면 된다.

접속하고, 도커를 설치한다.

sudo apt update
sudo apt upgrade -y // 시스템 업그레이드 & 업데이트  
  
sudo apt install docker.io -y // 도커 설치

sudo systemctl start docker
sudo systemctl enable docker // 도커 실행 및 도커 자동실행 on

여기에 추가로, 현재 사용자에게 도커 권한을 부여하려면

sudo usermod -aG docker $USER

하고 재접속 하면 된다고 한다(편의용).

이제 docker compose(여러 개의 컨테이너를 한번에 띄워주도록 해주는 것)도 추가로 설치한다.

sudo apt install docker-compose -y

이후 내 코드를 가져오기 위해 git을 설치 및 git clone을 통해 프로젝트를 가져온다.

sudo apt install git -y // git 설치
git clone <.git 링크> // github의 프로젝트 가져오기

이러면 EC2라는 가상 컴퓨터에 git, docker, docker compose, 그리고 내 프로젝트 코드까지 전부 설치가 완료된다.

6) 환경변수 설정(env) 및 docker compose(docker-compose.yaml), Dockerfile 설정하기 보안상 올릴 수 없었던 외부 인증키 등을 EC2에서 .env로 만들어 주입한다. 추가로 docker-compose.yaml도 설정한다.

nano .env // 이후 작업
nano docker-compose.ec2.yaml // ec2 빌드용 compose 파일을 하나 더 만들었다.

해당 yaml 파일에, 로컬과 비슷하게, 추가로 healthcheck 등의 내용을 넣어주었다.

이후 Dockerfile 또한 설정해준다.

cf: Dockerfile, docker-compose.yaml, application.yaml의 차이점

  • docker-compose.yaml이 Dockerfile을 읽어, 내 애플리케이션을 image로 만든다.
  • docker-compose.yaml에 적힌 대로, redis/mysql 및 내 애플리케이션 image를 가져와서 내가 설정한 환경변수(.env)가 application.yaml이 읽을 수 있도록 주입해준다.
  • 애플리케이션이 실행되면서, application.yaml이 읽히며 환경변수를 주입한다.

Dockerfile 설정내용 메모(이전 프로젝트 파일내용 참고함)

FROM gradle:8.7-jdk21 AS builder // gradle 있고, jdk 21 있는 이미지를 builder로 이름붙여 시작함
WORKDIR /app // 컨테이너 안에서 작업 시작할 위치
COPY . . // 컨테이너 안으로 파일을 가져오기 위해, 현재 EC2 안의 파일들을 현재 컨테이너 안 작업 위치로 전부 가져옴
RUN gradle clean bootJar -x test // gradle 실행, 이전 작업내역 삭제(clean), bootJar(내 애플리케이션 실행할때 필요한 모든것을 jar 파일로), -x test(테스트는 생략)

FROM eclipse-temurin:21-jre // jar 실행 가능한 깨끗한 새 이미지 가져옴
WORKDIR /app // 작업 시작할 위치는 /app, 아래 명령어에서 from=builder(아까의 builder 에서) /app/build/libs/*.jar app.jar(/app/build/libs/의 *.jar 파일을 쏙 빼와서 여기에 app.jar로 가져옴)
COPY --from=builder /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/app.jar"]

EXPOSE 8080으로 jre의 8080 포트를 열어주고, ENTRYPOINT로 자동 시작될때 java -jar /app/app.jar(아까 Dockerfile에서 복사해서 가져온) 실행한다. 즉 스프링 서버가 자동으로 뜨는 것이다.

이후 docker-compose -f docker-compose.ec2.yaml up -d –build 로 실행해보면(한 1분 정도 걸린다), 아래 사진처럼
ec2_success
정상적으로 공인IP:8080 으로 정상적으로 접속이 된다.

자고 일어나서 인스턴스 껐다가 다시 켜려면, 종료 절차를 아래와 같이 한다.
1) docker-compose -f docker-compose.ec2.yaml down 으로 컨테이너 내린 후 2) EC2 인스턴스를 중지한다.

다시 켜려면
1) EC2 인스턴스를 재가동한후, 공인 IP를 확인한다.
2) ssh -i 명령어로 다시 접속한다.
3) 이후 위의 docker-compose -f… 명령어를 다시 실행한다.

카테고리:

업데이트: