이벤트 기반 아키텍처 구조 현재 Gloddy 서비스는 그룹 시스템과 알림 시스템으로 구성되어 있습니다. 시스템 간 소통을 위해 이벤트 드리븐 방식을 사용하고 있습니다. 아래는 Gloddy 서비스의 아키텍처를 간단히 그림으로 나타낸 것입니다. 도메인의 비관심사는 메시징 시스템으로 이벤트를 발행하는 것입니다. 따라서, Spring Application Event를 활용해 도메인은 행위에 대한 이벤트를 발행하고, 이를 구독하고 있는 Sns Publish Listener에서 메시징 시스템으로 이벤트를 발행하도록 설계했습니다. 이를 통해 도메인에 영향 없이 메시징 시스템에 대한 연결을 변경 및 확장할 수 있습니다. 메시징 시스템으로는 SNS-SQS를 사용했습니다. 여러 도메인 행위에 대해 SNS 토픽을 생성하고,..
문제 상황 이전 글에서 Redisson을 사용해 분산 락을 구축했습니다. 이후 테스트를 통해 동시성 문제가 해결된 것을 확인할 수 있었습니다. 하지만, 다른 서비스에서 해당 메소드를 호출한 경우 동시성 문제가 재발되었습니다. 아래와 같은 상황입니다. TripMemberService에서는 트랜잭션을 시작하고, TripMemberCreateService의 create 메소드를 호출합니다. TripMemberCreateService에서는 분산 락을 획득하고, 여행 참여 인원을 1 증가시킨 뒤 여행 멤버를 생성합니다. @Service @RequiredArgsConstructor public class TripMemberService { private final TripMemberCreateService trip..
SSH을 통한 Git Clone SSH 프로토콜을 사용하여 Git Repository를 아래와 같이 clone할 수 있다. SSH 프로토콜을 사용하면 username과 password(token)을 입력하지 않고, push/pull 을 할 수 있다. $ git clone git@host:username/repository.git SSH 이란? SSH은 Secure Shell의 준말로, 공개 키와 비밀 키 한쌍(Key pair)을 이용해 인증하는 방식이다. 보통 공개 키의 경우 .pub, 개인 키의 경우 .pem의 파일 형식을 띄고 있다. 사용자의 컴퓨터에서 SSH 키를 생성하면 공개 키와 비밀 키가 생성된다. 해당 공개키를 Github에 등록해 컴퓨터를 인증할 수 있다. Github에 공개 키를 저장해놓..
Bulk Insert란? 아래와 같이 여러 개의 데이터를 하나의 Insert 쿼리로 삽입하는 것은 Bulk Insert라고 한다. 개별 Insert의 경우 쿼리를 던지고 응답을 받은 후에야 다음 쿼리를 전달하기 때문에 지연이 발생한다. 하지만 Bulk Insert는 하나의 트랜잭션으로 묶여 하나의 쿼리문으로 수행하기 때문에 성능이 좋다. -- Bulk Insert INSERT INTO last_insert_id_test(code) VALUES ('TEST1'), ('TEST2'), ('TEST3'); -- 개별 Insert INSERT INTO last_insert_id_test(code) VALUES ('TEST4'); INSERT INTO last_insert_id_test(code) VALUES (..
Github Action, ECR, S3, CodeDeploy를 활용해 Blue/Green 방식의 무중단 배포를 해보려 합니다. 아래는 모든 과정이 끝난 후의 아키텍처입니다. 배포 시나리오 1. Github에 코드 push하면 Github Action 동작 2. ECR에 Docker image push 3. S3에 CodeDeploy script 업로드 4. CodeDeploy 실행해 EC2 배포 Github Action을 통해 2,3,4 과정이 실행됩니다. ECR에는 Spring Boot docker image를 push하고, S3에는 CodeDeploy에 필요한 스크립트를 압축해 업로드 합니다. CodeDeploy에서는 S3의 스크립트를 실행해 EC2 배포를 진행합니다. 스크립트에는 ECR로부터 do..
문제 상황 oneToMany 관계에서 Fetch Join과 Limit을 같이 사용해 아래와 같은 경고 메시지가 발생했다. HHH90003004: firstResult/maxResults specified with collection fetch; applying in memory 쿼리 결과를 전부 메모리에 적재한 뒤 Pagination 작업을 어플리케이션 레벨에서 하기 때문에 위험하다는 로그이다. limit에 의해 제한된 개수의 쿼리 결과를 가져올 것이라는 예상과는 다르게 작동하고 있었다. 이처럼, One에서 Many를 fetch 하는 경우 limit절 (Pagination을 위해) 포함 시 원하는 대로 결과가 나오지 않고, 성능상 문제가 발생할 수 있다. 문제 상황 재현 문제 상황 재현을 위한 ERD이다..
Elastic Load Balancer의 종류인 Application Load Balancer를 생성해 트래픽을 분산해보자. 첫번째로는, 대상 그룹을 생성 후 인스턴스 2개를 대상으로 지정해 트래픽을 분산해보려 한다. 두번째로는, Auto Scaling Group을 대상 그룹에 연결해 Auto Scaling에 의해 생성된 모든 인스턴스들에 트래픽을 분산해보려 한다. 최종 아키텍처는 아래와 같다. Load Balancer Hands-On 시작 템플릿 버전 수정 Auto Scaling Group 시작 템플릿 변경 Target Group 생성 Application Load Balancer 생성 Auto Scaling Group을 대상 그룹으로 설정 Load Balancer 트래픽 분산 테스트 1. 시작 템플릿..
[ 개요 ] 서버를 운영하다 보면 hikari connection과 관련된 에러를 겪게 된다. 빈번하게 발생 가능한 에러라 정리해보려 한다. 먼저 ConnectionPool이 뭔지, HikariCP는 어떻게 동작하는지에 대해 알아보자. [ ConnectionPool ] ConnectionPool 이란 커넥션을 미리 생성해두고 사용하는 방법이다. 데이터베이스 커넥션을 새로 생성하는 것은 과정도 복잡하고, 많은 시간이 소요되므로 커넥션 풀을 사용한다. 커넥션 풀에 커넥션을 요청하면, 커넥션 풀은 자신이 갖고 있는 커넥션 중 하나를 반환한다. 커넥션을 모두 사용하고 나면 커넥션을 종료하는 것이 아니라 커넥션 풀에 반환한다. 커넥션 풀을 사용하면 커넥션 수를 제한할 수 있어 과도한 접속으로 인한 서버 자원 고갈..