코딩과 결혼합니다

[Game-Crew] 성능 테스트 : Redis 설치와 캐싱 기능 적용 본문

코딩과 매일매일♥/Game_Crew

[Game-Crew] 성능 테스트 : Redis 설치와 캐싱 기능 적용

코딩러버 2024. 1. 18. 15:43
728x90
설치 없이 편리하게 redis를 사용하고자 EmbeddedRedis의 종속성을 추가하고 성능테스트를 진행하려 하였다.
하지만 redis와의 서버 연결 문제가 해결되지 않았다. 

EmbeddedRedis는 일반적으로 테스트 코드에서 사용되며, 실제 운영 환경에서는 임베디드 형태로 동작하지 않는다고 한다. 

캐싱 기능을 접목시키고 jmeter와 같은 성능 테스트 도구를 활용하여 테스트를 진행하려면 Redis를 설치해야 한다.

https://coding-s2-chaewon.tistory.com/232

 

[Game-Crew] 트러블 슈팅 : 로컬에 Embedded Redis 적용(Chche, Redis)

배경 특정 유저의 프로필 조회 또는 평점 등록과 같은 반복되는 요청이 자주 발생하는 경우, 캐싱 기능을 활용하여 더 빠른 응답 속도를 제공하고자 Redis를 도입하기로 결정하였다. Embedded Redis는

coding-s2-chaewon.tistory.com


레디스 설치

https://redis.io/download

 

Download

Redis You can download the last Redis source files here. For additional options, see the Redis downloads section below. Stable (7.2) Redis 7.2 includes optimizations, several new commands, some improvements, bug fixes, and several new module APIs. It also

redis.io

이는 redis의 공식 사이트 다운로드 링크이다. 위 사이트에서 tar.gz 파일을 다운로드하여서 make 명령어들을 참고해 설치하는 방법이 있지만 Windows 같은 경우에는 이 과정이 복잡하고 설치가 어려울 수 있다. redis 자체에서는 윈도우는 지원하지 않아 공식 Github에서 zip파일을 다운로드하여도 마찬가지이다.

 

https://github.com/microsoftarchive/redis

 

GitHub - microsoftarchive/redis: Redis is an in-memory database that persists on disk. The data model is key-value, but many dif

Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes - GitHub - microsoftarc...

github.com

하지만  Microsoft redis Github에서 윈도우 사용자들을 위하여 redis 다운로드를 제공하고 있다.

우측에 Releases에서 버전 별로 redis를 다운로드할 수 있다. msi파일과 zip파일이 있는데 msi 파일을 다운로드하여서 설치하면 환경변수와 포트 메모리 등을 손쉽게 설정할 수 있다.


레디스 설정 변경

레디스의 설정변경은 redis.windows.conf 파일에서 수정할 수 있다.

1. 포트번호 변경

2. 비밀번호 변경

foobared 부분을 바꿔주면 된다.

 

그 외에도 메모리 최대 크기 설정이나 로그 파일을 설정할 수 있다.


레디스 실행

redis-server.exe 가 실행파일이다. 이를 클릭하면 6379 포트로 redis가 실행된다.

저걸 눌러도 창이 뜨지 않길래 문제가 있다고 생각했는데 

여기에서 정상적으로 redis가 동작하는지 간단하게 확인해 볼 수 있다. ping이라 치면 pong을 응답한다.

간단한 명령어로 테스트를 마친다.

시작메뉴의 검색바에 서비스라고 치면 서비스 앱이 나오고 여기서 이를 실행하고 끌 수 있다.


의존성 주입과 설정을 이미 했기 때문에 어플리케이션을 실행시켜보고 api성능 테스트를 바로 해보았다.

 

Troubleshooting(1)

▪️ 스프링에서 요펑과 응답의 데이터 변환을 처리하는 컨버터가 없음

ERROR 21616 --- [.0-8080-exec-20] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : 
Servlet.service() for servlet [dispatcherServlet] in context with path [] 
threw exception [Request processing failed: 
org.springframework.core.convert.ConverterNotFoundException: 
No converter found capable of converting from type 
[com.gamecrew.gamecrew_project.domain.user.dto.response.UserRatingsResponseDto] 
to type [java.lang.String]] with root cause

 

✔️ Redis Remplate 설정 확인

기존코드
@Bean
public RedisTemplate<String, UserRatingsResponseDto> redisTemplate(RedisConnectionFactory connectionFactory) {
    RedisTemplate<String, UserRatingsResponseDto> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);
    template.setValueSerializer(new GenericToStringSerializer<>(UserRatingsResponseDto.class));
    return template;
}

 

수정
template.setValueSerializer(new Jackson2JsonRedisSerializer<>(UserRatingsResponseDto.class));

 

더하여 UserRatingsResponseDto와 CustomPageable, UserRatingResultDto 클래스에 

@NoArgsConstructor 로 기본 생성자를 추가 해주었다.

🤔 GenericToStringSerializer 를 사용할 때에는 역직렬화를 위해 기본 생성자나 문자열을 객체로 변환하기 위한 매개변수를 가지고 있는 생성자가 필요하다고 한다. 그렇지 않으면 역직렬화 과정에서 오류가 발생할 수 있다.

반면에 Jackson2JsonRedisSerializer는 JSON 형식으로 직렬화하고 역직렬화하기 때문에, 객체의 구조를 유지하면서 역직렬화할 수 있다.
  • GenericToStringSerializer
    이 방식은 값을 문자열로 변환하여 저장하고, 역직렬화할 때에는 해당 문자열을 다시 객체로 변환한다. 이 방식은 단순한 문자열 직렬화이므로 객제의 구조를 유지하지 않고 값을 저장하게 된다. 따라서 객체의 필드명과 값만을 저장하고, 객체의 메서드나 상속 관계 등은 저장하지 않는다.
  • Jackson2JsonRedisSerializer
    이 방식은 Jackson 라이브러리를 사용하여 객체를 JSON 형식으로 직렬화하고, 역직렬화할 때에는 JSON을 다시 객체로 변환한다. 이 방식은 객체의 구조를 유지하고, 필드뿐만 아니라 메서드, 상속 관계 등을 포함하여 객체를 직렬화한다.

결과 - 처리하는 속도가 매우 빨라짐

이전과 같은 환경에서의 테스트를 진행하였다.

60초(1분) 동안 5000명의 유저가 동시에 API요청

 

https://coding-s2-chaewon.tistory.com/231

 

[Game_Crew] 성능 테스트 : JMeter 사용법과 테스트

JMeter 용어 Thread Group : 테스트에 사용될 쓰레드의 개수. (쓰레드 = 사용자) Sampler : 사용자가 취할 행동 (로그인, 게시물 작성, 조회 등) Listener : 응답을 받아 리포팅, 검증, 그래프 등 다양한 처리 Co

coding-s2-chaewon.tistory.com

캐싱 적용 전

Average 37459,
Min 0,
Max 77118,
std.Dev. 21974.84,
Error % 0.00%,
Througghput 36.6/sec,
Received KB/sec 36.30, 
Sent KB/sec 5.15,
Avg.Bytes 1015.0

 

캐싱 적용 후

Average 3,
Min 0,
Max 37,
std.Dev. 1.82,
Error % 0.00%,
Througghput 83.3/sec,
Received KB/sec 82.59, 
Sent KB/sec 11.72,
Avg.Bytes 1015.0
  캐싱 전 캐싱 후
평균 응답시간 37459 (37.459초) 3 (0.003초)
최대 응답시간 77118 (77.118초) 37 (0.037초)
응답 시간 변동 21974.84 (21.97484초) 1.82 (0.00182초)
처리량 36.6/sec 83.3/sec
수신 속도 36.30 82.59
송신 속도 5.15 11.72

 

이전 목표로 평균 응답시간을 1000ms 이하로 처리할 수 있도록 성능을 올려보고자 했었는데 3ms로 목표치를 매우 만족스럽게 달성하였다.


1만명의 유저가 60초동안 100명의 유저의 api를 동시에 조회할 때에는 어떨까?

열심히 추가했다.. 100개

Average 4,
Min 0,
Max 373,
std.Dev. 18.33,
Error % 0.00%,
Througghput 143.5/sec,
Received KB/sec 142.32, 
Sent KB/sec 20.26,
Avg.Bytes 1015.0

 

10000명의 조회가 1분 9초로, 9초가 초가되긴 하였지만 평균 응답시간이 4ms로 원하는 목표치 안에 들어온다.

유저의 평점을 조회하는 API는 여기서 성능테스트를 마치고 다음에는 유저의 평점을 등록하는 API의 성능을 높이고 테스트하는 시간을 가져봐야겠다.

 

참고

https://pamyferret.tistory.com/9