전체 글

전체 글

    [마이카마스터] 인덱스와 캐시를 이용한 측정에 의한 성능 개선

    [마이카마스터] 인덱스와 캐시를 이용한 측정에 의한 성능 개선

    상황 안정적인 서비스 운영을 위해선 모니터링 툴이 필수적이라 생각했고, 이에 따라 마이카마스터에 리소스 모니터링을 위해 prometheus를, APM으로는 Pinpoint를 적용했다. 적용 이후 Pinpoint로 API들의 응답 속도를 확인해보니, 성능 개선이 필요한 API들을 확인할 수 있었다. 그리고 이 중 응답속도 및 중요도를 고려해 우선순위를 설정했고, 결과적으로 지도 조회 API부터 개선하기로 결정했다. 병목 분석 먼저, 정확한 병목부터 분석하기로 했다. 지도 조회는 '대리점 목록 조회 쿼리'와, '카마스터 조회 쿼리'로 이루어져 있다. 지표 분석을 통해, 이 중 '대리점 목록 조회 쿼리'가 병목임을 확인했고, 이 쿼리부터 개선하고자 했다. 병목 제거 - 인덱스 이를 위한 수단으로 인덱스와 캐시..

    [마이카마스터] 비동기 처리를 통한 구매 상담 신청 API 개선

    [마이카마스터] 비동기 처리를 통한 구매 상담 신청 API 개선

    상황 견적서 확정 이후 구매 상담 신청시, 클라이언트에게 신청 확정 메일을 보내주고 있었다. 그런데 이 요청을 처리하는데 약 3 ~ 4초 라는 시간이 걸리고 있었고, 이로 인한 전체적인 서버 성능 저하가 우려되었다. 따라서 메일 서비스의 성능을 개선하고자 했다. 문제 분석 먼저 정확한 병목 구간을 파악하고자 했다. Pinpoint를 이용한 분석을 통해, 병목 구간이 어플리케이션 서버에 존재하는 것을 확인했는데, 이는 메일 전송이 동기적으로 진행되기 때문이었다. 그리고 긴 응답 시간도 문제였지만, 더 큰 문제는 트랜잭션 점유 문제였다. 부하 테스트 결과이다. 하나의 트랜잭션 안에서 메일 전송까지 처리하다보니, 10개 뿐인 커넥션 풀은 금방 고갈되었고, 뒤에 밀려드는 요청들을 트랜잭션을 얻기 위해 기다리다 ..

    [나날] 쿠폰 등록 동시성 처리를 위한 Lettuce 분산락 설정

    상황 후원자분들은 캐릭터 스킨을 적용할 수 있게하기 위한 수단으로 쿠폰을 선택하였다. 이렇게 발급된 쿠폰을 앱내에서 등록하면 해당 쿠폰을 만료된 쿠폰으로 변경하는데, 동시에 여러명이 쿠폰 등록시 모두 쿠폰이 등록될 수 있는 동시성 이슈를 발견했다. 사용기술: Mysql8.0, JPA 문제 분석 @Transactional public void checkSponsor(String socialId, String code) { Sponsor sponsor = sponsorRepository.findByCode(code) .orElseThrow(() -> CodeNotExistException.EXCEPTION); // 쿠폰 유효성 확인 checkCodeAlreadyUsed(); // 쿠폰 사용 처리 confir..

    [나날] 동시 요청시 Transaction Propagation 설정으로 인한 CP Deadlock 문제

    [나날] 동시 요청시 Transaction Propagation 설정으로 인한 CP Deadlock 문제

    문제 클라이언트로부터 동시 요청이 들어왔을때, 서버가 잠시동안 정상 동작하지 못하는 상황이 확인되었다. 문제 분석 Grafana 대시보드에 Connection Timeout Count가 증가된 것이 확인되었다. 서비스 특성상 지정된 connection-timeout 내에 처리가 불가능할만큼의 트래픽이 발생하지는 않았을 것이라 생각했고, Deadlock 발생으로 인한 문제를 예상하며 서버 로그를 확인하였다. // 스레드가 DB 커넥션을 요청한 시점으로부터 connection-timeout 만큼 지났을때 발생하는 로그들 HikariPool-1 - Connection is not available, request timed out after 5000ms. [CannotCreateTransactionExcept..

    [나날] 프록시 내부 호출을 고려한 트랜잭션 범위 최소화

    [나날] 프록시 내부 호출을 고려한 트랜잭션 범위 최소화

    문제 기존 코드에서 사용자 회원가입시에 플랫폼으로부터 사용자 정보를 요청하여 가져오는 로직이 트랜잭션안에 포함되어 있었다. 이에 따라 db 리소스가 오랜시간 점유되는 비효율이 발생했다. 문제 분석 @Service public class Auth { @Transactional public Response 회원가입_로그인(String accessToken) { // 플랫폼에서 사용자 정보 조회 ... // 회원가입 및 로그인 auth(member); // 토큰 관련 로직 ... } public void auth(Member member) { if(새로운 유저인지 체크) 회원가입 else 로그인 } } 코드를 보면, 트랜잭션이 회원가입_로그인 전체에 설정되어 실제로 트랜잭션안에 들어가지 않아도 될 부분들이 앞..