1. 무중단 배포란?프로젝트를 진행하며 기존의 배포방식에서는 새로운 서비스를 개발한 후 배포하게되면 서버가 중단되는 다운타임이 존재하는 단점이 있었습니다. 다운타임이 10초가량 걸린다 생각하면 그 10초동안은 유저들이 해당 서비스를 이용하지 못하는 상황이 생기게 됩니다. 이러한 중간에 서버가 다운되며 발생하는 다운타임을 무중단 배포를 통해 해결할 수 있습니다. 무중단 배포는 서비스의 버전이 변경되어 배포될 때 운영중인 서비스가 중단되지 않으면서 새로운 버전을 배포하는 방식으로 로드밸런서를 통해 연결된 두 개 이상의 인스턴스에 트래픽을 제어해 배포하게 됩니다.Rolling 방식Canary 방식Blue / Green 방식무중단 배포는 위와같은 3가지의 방식이 존재하는데. 지금부터는 각 3가지의 방식에 대해 ..
1. 문제 : 페이징 성능 이슈 발생프로젝트 진행 중, GCP에 배포된 Spring Boot 어플리케이션에서 페이징 기능을 성능 테스트한 결과, 충격적인 데이터를 확인하게 되었습니다. 100명의 유저가 1분 동안 요청을 보낸 결과 평균 TPS는 10.0, MTT는 9.082ms로, 매우 낮은 성능을 보였습니다. 부하 테스트 결과 분석네트워크 속도나 서버의 하드웨어 성능 문제일 가능성도 염두에 두었지만, 실제 원인은 데이터베이스 쿼리의 비효율성으로 보였습니다. 많은 수의 페이지 요청을 처리하면서 서버의 CPU와 메모리 사용량이 급증했고, 데이터베이스의 처리 시간이 특히 문제가 되었습니다. 기존 페이징 방식은 다음과 같은 흐름을 따르고 있습니다.기본 티켓 목록 페이징: 조건 없이 요청할 경우 예매 시작 날짜..
1. 개요최근 기존 모놀리식(monolithic) 아키텍처 기반의 티켓 예매 프로젝트를 MSA(Microservices Architecture)로 전환해보았습니다. 이번 포스팅에서는 전환 과정에 대해 다루기에 앞서, 먼저 모놀리식 아키텍처와 MSA란 무엇인지 간단히 살펴보고, 두 가지 아키텍처의 차이점을 비교해보려 합니다. 2. 모놀리식(monolithic) 아키텍처란?모놀리식 아키텍쳐란 모든 로직이 하나의 애플리케이션 형태로 패키지 되어 서비스되고, 애플리케이션에서 사용하는 데이터 또한 한 곳에 모인 데이터를 참조해 서비스되는 형태를 의미합니다. 위와 사진과 같이 애플리케이션이 하나의 패키지로 서비스 되기 때문에 배포가 단일 프로세스가 이루어져 간단하고, 한 곳에서 모든 로직을 관리할 수 있어 직관..
1. 개요프로젝트를 진행하며 티켓조회 성능 개선을 위해 캐싱 기능을 도입하기로 했습니다.티켓 데이터는 일단 생성되면 잘 수정되지는 않지만 사용자 요청이 집중될 때 자주 조회되는 특성이 있습니다. 이러한 특성을 고려해 티켓(공연) 정보를 조회 성능을 높이기 위해 캐싱을 도입하기로 결정했습니다. 2. 캐싱이란?캐싱은 데이터나 연산 결과를 미리 저장해두고 필요할 때 빠르게 접근할 수 있는 기술입니다. 일반적으로 반복적으로 조회되는 데이터나 연산속도가 느린 데이터를 저장하는 역할을 하며 캐시에 저장된 데이터는 원본 데이터에 비해 훨신 빠르게 접근할 수 있다는 장점이 있습니다. 이로 인해 시스템 응답속도를 개선하고, 서버의 부하를 줄일 수 있습니다.응답 속도 개선 : 캐시는 메모리같은 저장소를 활용하기 때문에 빠..
1. nGrinder란?nGrinder는 Naver에서 제공하는 오픈 소스 성능 테스트 도구로, 웹 애플리케이션, API, 서버의 성능을 측정하고 부하를 시뮬레이션하는 데 매우 유용한 도구입니다. 특히, 자바 기반의 스크립트 언어(Jython, Groovy)를 지원하여 코드 작성이 용이하며, 분산 환경에서 대규모 성능 테스트를 간편하게 수행할 수 있도록 설계되었습니다. 지금부터는 Ngrinder를 설치하고 스크립트 작성하는 방법을 알아보겠습니다. 2. docker-compose.yml 파일 작성version: '3.8'services: controller: image: ngrinder/controller restart: always ports: - "9000:80" ..
1. OpenFeign란?Spring Cloud OpenFeign은 넷플릭스가 개발한 Feign이라는 선언형 HTTP 클라이언트를 확장한 오픈 소스 프로젝트입니다. REST API 기반의 마이크로서비스 아키텍처에서 서로 다른 서비스 간의 통신을 더욱 간결하고 선언적으로 처리할 수 있도록 도와줍니다. OpenFegin은 선언형 방식으로 되어있어 인터페이스와 어노테이션을 정의하기만 하면, Spring이 실행 시점에 자동으로 해당 인터페이스의 구현체를 제공하여 API 통신을 손쉽게 수행할 수 있게 해줍니다. 이를 통해 개발자는 복잡한 HTTP 통신 로직을 신경 쓸 필요 없이, 마치 메서드 호출을 하듯이 외부 API와 통신할 수 있습니다. 2. Gradle 의존성 추가OpenFeign을 사용하기 위해 사용중인..
0. 개요프로젝트를 진행하면서 토스 간편 결제를 도입하기로 결정해서 토스 개발자 센터의 문서를 따라가보며 해당 기능을 구현해 보았습니다.토스의 결제는 위의 그림처럼 진행되는데 서버의 역할인 결제승인 API를 호출하고 해당 응답을 처리하는 기능만 구현해보았습니다. 1. 토스 개발자 센터에서 시크릿 키 발급받기토스 개발자센터에서 시크릿 키를 발급받습니다. (노출되지 않도록 조심!) 저는 실제 운영환경이 아닌 개인 프로젝트를 진행하기 때문에 테스트 키를 통해 진행해보도록 하겠습니다.(테스트 키를 통해 일어난 결제는 이뤄지지 않고 가상으로 이뤄집니다.) 2. 발급받은 키를 이용하기 위해 yml설정을 추가하기application.ymlpayment: secret-key: 시크릿키 넣어줍시다 base-url: ..
1. 상황티켓 예매를 진행하면서 결제 기능을 도입하면서 결제가 성공하면 Reservation의 Status를 변경해야하는 요구사항이 존재했습니다. 해당 로직을 구현하면 아래와 같습니다.@Service@Transactionalpublic class PaymentService { private final PaymentClient paymentClient; private final PaymentRepository paymentRepository; private final ReservationService reservationService; public PaymentService(final PaymentClient paymentClient, final PaymentRepository pay..
Redis를 활용한 분산 락(Distributed Lock) 구현하기분산 락은 분산된 서버에서 공유 자원에 동시에 접근하는 것을 제어하기 위해 사용되는 방식으로, 락에 대한 정보를 어딘가에 공통적으로 보관하고 여러대의 서버들은 이 공통된 보관소를 바라보며 임계 영역에 접근할 수 있는지 확인하게 되는데, 공통된 보관소로는 주로 Redis, Zookeeper, MySQL 등이 사용됩니다. 그 중 Redis를 사용해 분산 락을 구현해보도록 하겠습니다. Lettuce vs RedissonRedis를 활용한 분산 락에 구현되는 대표적인 RedisClient는 Lettuce와 Redisson이 존재합니다.Lettuce : Spin Lock 방식으로 락에 대한 획득 시도를 지속적으로 수행하며 락에 대한 타임아웃 지정..
1. 문제점티켓 예매 특성상 특정시간에 엄청난 사람이 한꺼번에 몰려 예매를 시도하게 됩니다. 이 때 같은 좌석은 여러명이 예매할 수 없도록 해야하는데, 동시성 문제에 대한 처리가 없는 상황에서 여러명이 예매 요청을 할 경우에는 같은 좌석에 여러명의 사람들이 예매가 되는 문제가 발생하게 됩니다. 그렇다면 이런 상황이 왜 벌어지게 되는걸까요? 테스트 실행멀티 쓰레드를 이용해 100명의 사용자가 동시에 예매를 진행하는 테스트 코드를 작성해 해당 문제를 확인해봅시다. @Test void 티켓예매시_좌석_동시성_테스트를_진행한다() throws InterruptedException { List seatIds = List.of(1L); ReservationRequest reque..