Skip to content

thdefn/twentysix

Repository files navigation

  RUNRUN

   Last commit pass the coverage codecov README Updated At

선착순 주문은 RUNRUN 에서❕

RUNRUN 은 상품에 대한 선착순 구매 기능을 지원하는 서비스입니다.
저희 서비스는 높은 트래픽 상황에서도 유저에게 원활한 구매 경험을 제공하는 것을 목표로 하고 있습니다.
서비스의 특징은 아래와 같습니다.

상품 별 서킷 브레이커를 도입해 시스템 안정성 확보 #92
주문 요청이 폭주되는 상황에서, 시스템의 안정성을 확보하기 위해 상품에 대해 서킷 브레이커를 적용했습니다.
이를 통해 시스템의 신뢰성과 가용성을 유지하고, 대규모 트래픽 상황에서도 안정적으로 서비스를 제공할 수 있습니다.

주문 서버의 자동 확장을 통한 유연한 대응 #111
대규모 트래픽 상황에 적절히 대응하기 위해 주문 서버에 오토 스케일링을 적용했습니다.
이를 통해 트래픽이 급증할 때 서버 리소스를 자동으로 확장하여 서비스 중단 없이 안정적인 주문 처리가 가능하도록 했습니다.

재고 관리에 분산락을 적용해 데이터 무결성 보장 #70
다수의 사용자가 동시에 주문을 시도하는 상황에서 데이터의 무결성을 보장하기 위해 분산 락을 적용했습니다.
이를 통해 경쟁 조건을 방지하고, 정확한 재고 관리와 안정적인 주문 처리가 가능하도록 했습니다.

Documents

🔗 API Document

🔗 ER-Diagram

🔗 Coverage Report

Technologies Used

Deploy   |  
Language   |  
Frame Work   |  
Data Source   |  
Inter Communication   |  
Coverage   |  
ETC   |  

Version Detail
  • Java 22
  • Python 3.9
  • Gradle 8.8
  • Spring Boot 3.3.2
  • Kafka 3.8.0
  • MySQL 8.0
  • MongoDB 7.0.12
  • Redis 7.4
  • gRPC 1.66.0

Architecture

Infra Structure Diagram

infra-structure

서버 간 통신

  • gRPC를 사용하여 서버 간의 직접 통신을 구현했습니다. gRPC는 높은 성능과 낮은 지연 시간을 제공하여, 서비스 간의 데이터 교환을 신속하고 안정적으로 처리할 수 있습니다.
  • kafka를 활용하여 서버 간의 간접 통신을 구현했습니다. 이를 통해 더 유연한 데이터 처리가 가능해 시스템의 전체적인 효율성을 향상시켰습니다.

Redis 글로벌 캐시 노드 사용

  • Redis를 글로벌 캐시 노드로 활용하여, 클러스터 내 모든 노드가 공유하는 캐시를 구현합니다. 이 구조는 스케일링에 적합하며, 모든 노드가 공통된 캐시를 사용함으로써 데이터 일관성을 유지할 수 있습니다.

Kubernetese Architecture Diagram

k8s-architecture

내외부 트래픽 관리 지점 분리

  • Ingress는 외부 트래픽을 관리하고, 모든 외부 요청을 API 게이트웨이로 전달합니다.
  • API 게이트웨이는 내부 트래픽을 관리하고, 인증과 인가를 중앙에서 처리하여 시스템의 보안과 일관성을 강화합니다.
    • API 게이트웨이의 고가용성을 보장하기 위해 replica 를 설정하여 장애 발생 시에도 시스템의 접근성을 유지합니다.

오토 스케일링

  • HPA를 활용하여 주문 서버와 게이트웨이 서버의 replica 수를 자동으로 조정합니다. 서버의 부하에 따라 적절히 스케일링하여, 높은 트래픽 상황에서도 안정적으로 대응할 수 있습니다.

배치 처리

  • CronJob을 활용하여 정기적인 배치 작업을 자동화했습니다. 설정된 시간과 주기에 따라 자동으로 실행되어 데이터 처리 작업을 효율적으로 관리하고, 시스템 운영의 안정성을 높입니다.

Directory Structure

 ┣ 📂 .github
 ┃ ┗ 📂 workflows
 ┣ 📂 gateway
 ┣ 📂 user
 ┃ ┃ 📂 src/main/resources
 ┃ ┃ ┗ 📜 application-dev
 ┃ ┃ ┗ 📜 application-test
 ┃ ┣ 📜 Dockerfile-dev
 ┃ ┗ 📜 Dockerfile-test
 ┣ 📂 brand
 ┣ 📂 order
 ┣ 📂 payment
 ┣ 📂 product
 ┣ 📂 cron-jobs
 ┣ 📂 kubernetese
 ┣ 📂 load-test
 ┃ ┗ 📜 docker-compose-load-test.yml
 ┣ 📂 infra
 ┣ 📜 build.gradle
 ┣ 📜 settings.gradle
 ┗ 📜 .gitignore
Description
  • 📂 workflows : 테스트 커버리지 체크와 API 문서 통합 빌드를 자동화하는 워크플로우 파일이 포함되어 있습니다.
  • 📂 gateway : 사용자의 인증과 권한 부여를 담당하는 엔드포인트 서버입니다.
  • 📂 user : 회원 가입, 로그인, 회원 정보 관리 등을 담당합니다.
  • 📂 brand : 상점 생성, 수정, 조회 등 판매자의 상점 관리를 담당합니다.
  • 📂 order : 유저의 상품 주문, 조회, 취소, 장바구니 등을 담당합니다.
  • 📂 payment : 결제 요청, 결제 취소 등을 담당합니다.
  • 📂 product : 상품 등록, 조회, 수정, 삭제 등을 담당합니다.
  • 📂 cron-jobs : 주기적으로 실행되는 배치 작업을 담당하는 스크립트를 포함합니다.
  • 📂 kubernetese : 쿠버네티스 관련 구성 파일과 스크립트가 모여 있는 폴더입니다.
  • 📂 load-test : 부하 테스트 스크립트와 도커 컴포즈 구성 파일을 포함합니다.
  • 📂 infra : 서버의 전체 인프라를 구성하는 데 필요한 도커 컴포즈 파일을 포함합니다. 이 폴더는 인프라 배포와 설정을 자동화하는 데 사용됩니다.
  • 📜 build.gradle : 하위 모듈에 공통으로 필요한 종속성을 선언합니다. 각 서버 간의 의존성을 최소화하기 위해, 하위 모듈의 테스트 커버리지 통합과 같은 필수적인 작업만을 포함합니다.
  • 📜 settings.gradle : 하위 모듈을 선언합니다.
  • 📜 .gitignore : git 에 올라가지 않아야 할 파일을 정의합니다.
  • 📜 docker-compose-load-test.yml : 부하 테스트 환경을 위한 서버 컨테이너와 모니터링 도구 등을 정의합니다.
  • 📂 **/📜application-dev.yml : 개발 환경에 반영될 환경변수를 세팅합니다. 모든 서버 모듈이 포함하고 있습니다.
  • 📂 **/📜application-test.yml : 테스트 환경에 반영될 환경변수를 세팅합니다. 모든 서버 모듈이 포함하고 있습니다.
  • 📂 **/📜Dockerfile-dev.yml : 개발 환경에 쓰일 도커 이미지를 빌드합니다. 모든 서버 모듈이 포함하고 있습니다.
  • 📂 **/📜Dockerfile-test.yml : 테스트 환경에 쓰일 도커 이미지를 빌드합니다. 모든 서버 모듈이 포함하고 있습니다.

Performance Optimization

Circuit Breaker

상품 별 서킷 브레이커를 도입해 시스템의 안정성을 향상시키고 서버 리소스를 절약했습니다.

test-case
  • 10,000명의 사용자와 초당 300명의 유저를 가정한 고부하 환경에서 성능 테스트를 진행했습니다.
  • 테스트는 주문 요청, 결제 페이지 진입, 결제 요청의 순서로 수행되었습니다.

Before Applying Circuit Breaker

before-circuit
  • 서킷 브레이커 도입 전에는 대규모 사용자가 몰릴수록 주문 서버에서 커넥션 에러가 빈번하게 발생했습니다.
  • 전체 에러 중 67%가 처리되지 않은 커넥션 에러였으며, 최대 응답 시간은 약 70초에 달했습니다.
  • 주문 서버의 병목 현상으로 인해, 주문 서버와 연동된 결제 API의 응답 시간도 지연되었습니다.

After Applying Circuit Breaker

after-circuit
  • 상품별 서킷 브레이커를 도입하여, 특정 상품 주문에서 10%의 에러가 발생하면 30초 동안 해당 상품을 포함한 주문에 대해 즉시 에러 응답을 하도록 설정했습니다.
  • 메인 주문 로직 이전에 서킷 브레이커가 작동해 빠르게 오류를 감지하고, 불필요한 서버 자원 소모를 줄였습니다.
  • 그 결과 커넥션 에러는 1% 이하로 감소했으며, 최대 응답 시간도 30초 이내로 줄어 서킷 브레이커 도입 전보다 50% 향상되었습니다.

Technical Decision

Distributed Lock : Redisson Lock


Redis Custom Lock Redisson Lock Redis의 싱글 스레드 특성 활용
장점 - 간단한 구현
- Pub/Sub을 활용하여 네트워크 요청 최소화 - 원자적 작업 보장
- 가장 적은 네트워크 비용
단점 - 지속적인 네트워크 요청 필요
- Redisson 라이브러리에 대한 학습 필요 - 코드 복잡도 증가
  • 데이터 무결성을 보장하기 위해 Redis를 활용해 분산 락을 구현했습니다.
    • Redis는 메모리 기반 데이터 저장소로, 매우 빠른 읽기/쓰기 성능을 제공하여 락을 신속하게 획득하고 해제할 수 있습니다.
  • MSA 환경에서 노드가 확장될 때, 락 메커니즘을 확장할 수 있어야 합니다.
  • 따라서 네트워크 오버헤드가 적고, 클러스터 환경에서도 안정적으로 동작할 수 있는 Redisson 방식을 선택했습니다.



Direct Messaging : gRPC


gRPC HTTP
장점 - 인코딩/디코딩 속도가 빠름
- 통신 효율성 높음
- 상대적으로 쉬운 기술 도입
단점 - 러닝 커브가 있음
- 설정과 학습 필요
- 높은 트래픽에서 성능 저하 가능성
  • MSA 환경은 서버 간 통신이 높은 성능과 낮은 지연 시간을 요구합니다.
    • 각 도메인 간 데이터 교환이 빈번하게 이루어지기 때문에, 통신이 느리면 전체 시스템의 응답 시간이 지연될 수 있습니다.
  • 따라서 도입에는 러닝 커브가 있지만, 높은 성능과 낮은 지연 시간을 충족할 수 있는 gRPC를 선택했습니다.



User Flow

Order Flow

Flow Chart

order flow

주문 실패
1. 주문 시, 상품에 대한 재고를 체크합니다.
2. 재고가 부족하다면 유저는 주문 실패 응답을 받습니다.





결제 실패
1. 결제 시, 상품에 대한 재고를 체크합니다.
2. 재고가 부족하다면 유저는 결제 실패 응답을 받습니다.
3. PG사에 결제를 요청합니다.
4. 잔액 부족 등 고객 귀책으로 인한 최종 결제 실패 시 유저는 결제 실패 응답을 받습니다.

Sequence Diagram

sequence-diagram

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages