윈도우 환경에서 Spring Cache
사용여부에 따른 성능 비교를 위해 Vegeta
라는 툴을 사용해보고자 한다. Cache는 Redis Cache를 사용한다.
local ip 확인해두기
Vegeta
설치 전 명령프롬프트에서 ipconfig를 통해 local의 IPv4 주소를 확인해두자.
Vegeta 설치
윈도우 환경에서 Vegeta
설치를 위해서는 WSL
를 이용하여 ubuntu
를 설치해줘야 한다.
윈도우에 ubuntu 설치
WSL
로 설치한 ubuntu
에 접속하고 Vegeta
를 설치한다
sudo snap install vegeta
참고 : 스냅(Snap)은 우분투의 개발사인 캐노니컬에서 개발한 패키지 관리 시스템이다
아래 명령어를 통해 스냅으로 설치된 패키지 목록을 확인할 수 있다.
snap list
주요 명령어 및 파라미터
공통 명령어
- vegeta attack: HTTP 요청을 특정 속도 및 시간 동안 실행하여 부하를 생성.
- vegeta report: 부하 테스트 결과를 요약 보고서로 출력.
주요 파라미터
vegeta attack [옵션]
-targets: 부하를 보낼 대상 파일 경로.
-rate: 초당 요청 수
-duration: 부하를 지속할 시간.
-timeout: 각 요청의 타임아웃 시간.
-workers: 요청 처리에 사용될 워커(스레드) 수.
간단한 성능 테스트
Vegeta
를 설치하고 아래의 명령어를 실행하여 간단히 성능 테스트를 실행해볼수 있다.
5초동안 초당 10회의 GET 요청을 http://example.com
으로 보내고 그 결과를 확인하는 명령어이다.
echo "GET http://example.com" | vegeta attack -rate=10 -duration=5s | vegeta report
결과를 통해 총 초당 10.21의 빈도로 50번의 요청을 보냈고 , 5.038s 동안 4.899s 요청을 보내고 138.946ms 동안 응답을 기다렸음을 알 수 있다.
-targets 옵션
위의 예시에서는 http://example.com
이라는 단일 타겟으로 GET
요청을 보냈지만, 여러개의 요청을 보내고 싶을 경우 파일에 보낼 요청을 작성하고 -targets
옵션을 통해 해당 파일의 경로를 지정해주면 해당 파일의 요청들을 지정해준 옵션에 따라 보낼 수 있게 된다.
아래와 같이 request.txt 파일을 작성하였다.
GET http://192.168.55.68:8080/users/1
GET http://192.168.55.68:8080/users/2
GET http://192.168.55.68:8080/users/3
명령 작성
공통 명령어와 파라미터를 참조하여 다음과 같이 vegeta attack
명령어를 작성하였다.
최대 20초의 타임아웃으로 100개의 스레드로 10초동안 초당 3천번의 요청을 보낸다.
vegeta attack -timeout=20s -duration=10s -rate=3000/1s -targets=request.txt -workers=100 | vegeta report
위 명령을 한 번은 캐시를 적용시킨 코드를 주석처리하여 빌드 한 다음 실행시키고, 한 번은 캐시를 적용시킨 다음 빌드하여 실행시키면 캐시를 적용하였을 때와 적용시키지 않았을때의 성능 차이를 비교할 수 있게 된다.
@Cacheable(cacheNames = CACHE1, key = "'user:' + #id")
public User getUserFromCache(final Long id) {
return userRepository.findById(id).orElseThrow();
}
위 코드의 @Cacheable
어노테이션을 주석처리 할 경우 캐시가 적용되지 않고 매 요청에 대해 DB에 직접 조회하게 될 것이고, 주석처리 하지 않을 경우 첫 요청에 대해서만 DB에 직접 조회하고 그 이후 요청부터는 Redis에 저장된 캐시를 불러오게 될 것이다.
실행 결과
위 vegeta
명령어를 캐시 적용 전후 각각 실행하고, 실제 유저 데이터와 캐시데이터가 저장될 redis
와 mysql
도커 컨테이너의 리소스 모니터링을 통해 캐시 적용 전후의 CPU 점유율 등을 확인해보았다.
캐시 적용 전
총 24.309s 동안 절반이상의 시간을 응답을 기다리는데 쓰였고, 요청에 대해서는 99.49% 성공했지만 초기 원했던 초당 3000회의 요청에 미치지 못하는 초당 1665.66번의 요청이 수행된것을 알 수 있다. 캐시를 사용하지 않으면 매 요청에 대해 DB에 쿼리를 날리게 되고 그 만큼 부하가 가해지므로 성능이 좋지않음을 알 수 있다.
왼쪽이 redis 컨테이너, 오른쪽이 mysql 컨테이너의 리소스이다. 캐시를 적용하지 않았기 때문에 redis 컨테이너의 CPU 점유율은 거의 변동이 없는 반면 mysql 컨테이너는 70%까지 CPU 점유율이 올라갔다.
캐시 적용 후
같은 요청에 대해 캐시를 적용시켜보니 10.008s 동안 응답 대기 시간은 고작 6.129ms에 불과했고, 초당 2999.40회 요청이 이뤄졌으며 요청이 100% 성공했음을 알 수 있다. mysql
과 redis
의 CPU 점유율 또한 레디스 서버가 한때 6~7%까지 점유율이 올라가긴 하였으나 비교적 안정적으로 유지 되었다. 확실히 캐시를 적용하였을 때 부하가 덜하고 좋은 성능이 나옴을 알 수 있었다.