[TIL] 241204 대규모 스트림 처리 입문, RabbitMQ

MONA·2024년 12월 4일

나혼공

목록 보기
41/92

오늘의 알고리즘

코드카타는 매일 진행된ㄷㅏ...
하면 할수록 파이썬이 그리워진다.

프로그래머스-개인정보 수집 유효기간

문제 분석

  • 주어진 것
    • today: 오늘 날짜
    • terms: 약관 종류와 유효기간(개월 수)
    • privacies: 개인정보 수집일과 동의한 약관 종류
  • 날짜 비교
    • today와 비교해서 만료일이 지나면 개인정보의 인덱스를 결과에 추가해서 반환

아이디어

  1. 날짜를 숫자로 변환해서 비교
    • 어차피 한달의 기준을 28일로 잡기 떄문에 이를 하나의 정수 값으로 변환해서 비교함
  2. 약관별 유효기간 관리
    • terms 배열은 "A 3" 이런 형식으로 저장됨
    • Map에 저장해 빠르게 조회할 수 있음
  3. 만료일 계산
    • 수집일 + 약관별 유효기간으로 만료일 계산
  4. 만료일 비교
    • today 이전이면 결과에 추가 후 반환
import java.util.*;

class Solution {
    public int[] solution(String today, String[] terms, String[] privacies) {
        Map<String, Integer> termMap = new HashMap<>();
        for (String term : terms) {
            String[] splitTerm = term.split(" ");
            termMap.put(splitTerm[0], Integer.parseInt(splitTerm[1]));
        }

        int todayDays = toDays(today);

        List<Integer> expiredIndices = new ArrayList<>();
        for (int i = 0; i < privacies.length; i++) {
            String[] privacy = privacies[i].split(" ");
            int startDays = toDays(privacy[0]);
            String termType = privacy[1];

            int expirationDays = startDays + termMap.get(termType) * 28;

            if (expirationDays <= todayDays) {
                expiredIndices.add(i + 1); 
            }
        }

        return expiredIndices.stream().mapToInt(Integer::intValue).toArray();
    }

    private int toDays(String date) {
        String[] parts = date.split("\\.");
        int year = Integer.parseInt(parts[0]);
        int month = Integer.parseInt(parts[1]);
        int day = Integer.parseInt(parts[2]);
        return (year * 12 * 28) + (month * 28) + day;
    }
}

풀이

  • termMap: HashMap으로 선언해 약관별로 유효기간을 저장
  • todayDate: today는 정수로 변환해서 사용
  • expiredIndices: 만료된 개인정보 인덱스를 저장할 배열
  • privacies 배열을 순회하면서 수입일과 약관 종류를 파악하여 약관에 따른 만료일을 계산한다
    • startDays: 수집일
    • termType: 약관 종류
  • 오늘 날짜보다 작으면 배열에 추가한다
  • toDays: 날짜를 일 단위로 변환
    • ex) "2022.05.19" → (2022 × 12 × 28) + (5 × 28) + 19 = 847919

잠온당...


대규모 시스템이란?

수백만 명의 사용자가 동시에 접속, 상호작용하는 환경에서
단순히 많은 사용자를 처리하는 것 뿐만 아니라 안정성과 신뢰성을 유지하면서 고성능을 제공할 수 있는 시스템
대규모 시스템의 맥락에서 실시간 데이터를 빠르게 처리하고, 적합한 결과를 추출하는 프로세스!

이런 특징이 있다.

특징

  1. 데이터 양이 매우 큼
    • 데이터가 기하급수적으로 증가하며, 초당 수십만에서 수백만 건의 데이터를 처리해야 하는 상황
    • 예: SNS 플랫폼(트위터, 인스타그램), IoT 센서 네트워크, 금융 거래 시스템
  2. 고가용성
    • 시스템이 중단 없이 작동해야 하며, 데이터 유실이 없어야 함
    • 예: 실시간 거래 시스템, 스트리밍 서비스(ex: 넷플릭스)
  3. 분산 아키텍처
    • 단일 서버가 아닌 여러 대의 서버(클러스터)로 이루어진 분산 환경에서 데이터가 처리됨
    • 확장성과 내결함성이 장점
  4. 확장성
    • 데이터 양이나 사용자가 증가해도 시스템이 성능 저하 없이 확장 가능해야 함
    • 예: 클라우드 기반 확장형 인프라(AWS, GCP)
  5. 실시간 처리
    • 데이터가 생성됨과 동시에 실시간으로 처리 및 분석이 이루어져야 하는 경우
    • 예: 실시간 로그 분석, 광고 시스템

하여간 겁나 멋있는 시스템이란 것이다.
대규모 시스템을 설계, 구축하는 과정에서 고려해야 할 요소들을 알아보자!

목표

  • 대규모 스트림 처리에 대한 이해
  • 대규모 시스템의 전반적인 구성과 운영에 대한 이해

시스템 설계의 기준

1. 동시 접속자와 초당 요청량(TPS)

1-1 사용자수

  • 몇 명의 사용자가 시스템을 사용할 것인지 파악하는 것이 중요함
  • 하루에 몇 명의 사용자가 접속하는 지도 알아야 하지만 동시 접속자의 요청 수도 중요!

1-2 TPS (Transactions Per Second)

  • 초당 처리되는 트랜젝션의 수를 나타내는 지표

  • 시스템이 동시에 얼마나 많은 요청을 처리할 수 있는지를 나타냄. 이를 바탕으로 시스템의 처리 능력을 파악할 수 있다

  • 일간 접속량보다는 초당 접속자 요청량이 가장 많은 특정 시간을 파악하고 이를 통해 시스템 용량 계획을 세워야 한다

  • 예기치 못한 트래픽 증가를 버틸 수 있는 설계를 하는 것이 목표

  • "예기치 못한 이벤트"로 인해 설계 이상의 요청이 몰린다면?

    • 애플리케이션의 수를 늘려서 버틴다
    • 오류 상황에서 사용자가 대기할 수 있는 대기열을 설정한다
    • 오토 스케일링을 통해 시스템 자원을 동적 할당하여 부하를 분산시킨다

2. 요청 종류에 따른 개발

  • 시스템이 읽기 전용인지, 쓰기 및 업데이트를 위한 것인지도 고려해야 함
  • DB에서 데이터를 조회하거나 쓰는 것은 많은 리소스를 먹는다. 이 부분의 허들을 최소화 하는 것이 중요

2-1. 읽기 요청 최적화

캐시 사용

  • 모든 사용자가 같은 데이터를 요청하는 경우, DB 데이터를 레디스 같은 곳에 캐싱해두면 응답 속도를 빠르게 할 수 있다

  • 개인화 데이터가 아니라면 캐시를 사용하는 것이 중요한 전략일 수 있다

  • 엣지 단에서 캐싱 처리를 하면 시스템 요청 처리량이 줄어들어 적은 수의 애플리케이션으로도 요청을 처리할 수 있다

    • 엣지 캐싱: 사용자와 가까운 곳에서 데이터를 제공하여 네트워크 지연을 최소화 함
  • 캐시 갱신 전략에서도, 변경이 적은 데이터는 만료 시간을 길게, 변경이 잦은 데이터는 만료 시간을 짧게 설정하거나 변경 시점에 캐시를 무효화하는 전략을 이용할 수 있다

  • 캐시 계층에서 데이터 소실 시 재요청을 통해 DB에서 다시 갖다놓는 것도 중요하다

데이터베이스 사용 최적화

  • 데이터베이스 인덱싱

    • 적절한 인덱스 설정은 읽기 성능을 최적화하여 쿼리 응답 시간을 줄일 수 있음
    • 인덱스가 과도할 경우 쓰기 성능이 저하될 수 있음
  • 데이터베이스 샤딩

    • 데이터베이스를 여러 샤드로 분할해 각각의 샤드가 독립적으로 쿼리를 처리하도록 하는 방법
    • 단일 데이터베이스에 대한 부하를 분산시키며, 읽기 요청에 대한 응답 속도를 향상시킬 수 있음
  • 읽기 전용 데이터베이스

    • 데이터를 주기적으로 동기화하여 최신 상태를 유지하며 읽기 요청을 처리
    • 주 데이터베이스에 대한 읽기 부하를 줄이고 성능을 최적화 할 수 있음
  • 쿼리 최적화

    • 쿼리를 효율적으로 작성하여 데이터베이스의 읽기 성능을 향상시키는 방법
    • 불필요한 join 제거, 필요 컬럼만 추출, 적절한 조건 사용 등

2-2. 쓰기 요청 최적화

쓰기 작업에서 가장 많은 시간이 소요되는 것은 DB에 데이터를 생성하는 부분이다

비동기 처리

  • 쓰기를 비동기 처리하면 DB에 직접 접근하지 않고도 빠르게 응답을 반환할 수 있다

  • 메시지를 바로 DB에 쓰지 않고 큐에 넣어 나중에 처리하는 등

  • 비동기 처리는 높은 트래픽 처리에 특히 유용하다

  • 비동기 처리 시 데이터 소실이나 오류를 방지하기 위해 큐에 넣을 때 적절한 검증 수행, 큐에 쌓인 데이터를 지속적으로 모니터링해 실패 요청은 재시도하는 매커니즘 마련 필요

  • 데이터 순서를 보장하고, 중복 처리 방지를 위한 고유 식별자(ID) 사용

배치 처리

  • 실시간 처리가 필요 없는 쓰기 요청은 배치 처리를 통해 한번에 처리

  • 일정 시간마다 큐에 쌓인 메시지를 DB에 쓰는 방법 등

  • 실시간 처리의 부담을 줄이고 시스템 자원을 효율적으로 사용 가능

  • 데이터 소실 방지를 위해 배치 작업 중 오류 발생 시 이를 기록하고 재시도할 수 있는 매커니즘 필요

  • 배치 작업의 상태를 모니터링하고 배치 작업이 완료되었는지 확인하는 프로세스 필요

분산 DB

  • 단일 DB로 모든 쓰기 요청을 처리하기 어려울 경우, 분산 DB를 사용하여 부하를 분산시킬 수 있음

  • 여러 개의 DB 인스턴스를 사용해 각 인스턴스가 특정 사용자 그룹의 데이터를 처리하도록 할 수 있음

  • 데이터를 여러 개의 노드에 분산 저장하여 고가용성, 확장성 제공

  • 샤딩 기법을 통해 DB를 수평 분할하여 각 샤드가 독립적으로 쓰기 작업을 하게 할 수도 있음
    -> 단일 노드의 부하를 줄이고 전체 시스템의 능력을 향상시킬 수 있다

  • 데이터 일관성 유지를 위해 트렌젝션 관리와 데이터 동기화를 신중히 고려해야 한다
    -> 분산 트렌젝션이나 이벤트 소싱을 이용

3. 데이터 일관성 유지

분산 트렌젝션, 이벤트 소싱, CQRS 등의 기법을 이용할 수 있다

3-1. 분산 트렌젝션

여러 개의 독립된 시스템이나 데이터베이스에서 동시에 일어나는 트렌젝션을 일관되게 관리하는 방법

주요 개념

  • 트랜젝션
    • 데이터베이스의 상태를 변환하는 작업의 단위. ACID 속성을 보장함
    • 원자성: 전부 성공하거나 전부 실패해야 함
    • 일관성: 트랜젝션 완료 후에도 데이터베이스는 모든 무결성 제약 조건을 유지
    • 격리성: 동시 실행되는 트랜젝션이 서로 간섭하지 않도록 보장
    • 지속성: 트랜젝션이 성공적으로 완료된 후의 결과는 시스템 장애가 발생해도 영구 유지됨
  • 분산 트랜젝션(Distributed Transaction)
    • 여러 분산된 데이터 소스에 걸쳐 트랜젝션을 수행함
  • 2PC (Two-Phase Commit)
    • 분산 트랜젝션을 관리하는 프로토콜. 준비단계(prepare)와 커밋(commit) 단계로 나누어 트랜젝션 처리
    • 준비 단계(Prepare Phase): 각 참여 노드는 트랜젝션 준비 상태를 확인하고, 준비 완료를 마스터 노드에 알림
    • 커밋 단계(Commit Phase): 마스터 노드는 모든 참여 노드가 준비되었음을 확인하고 트랜젝션을 커밋하도록 지시함. 준비되지 않은 노드가 있다면 롤백
  • 사가 패턴(SAGA Pattern)
    • 트랜젝션을 여러 단계로 나누어 처리하고, 각 단계가 독립적으로 커밋함
    • 실패 시 보상 트랜젝션을 실행하여 상태를 롤백
  • 이벤트 소싱(Event Sourcing)
    • 상태 변화를 이벤트로 기록하고, 해당 이벤트를 재생해 현 상태를 유지

단점

  • 복잡성 증가
  • 성능 저하: 2PC와 같은 프로토콜 사용 시 트랜젝션의 준비와 커밋 단계에서 지연이 발생할 수 있음
  • 네트워크 오버헤드: 여러 시스템 간의 통신이 필요하므로 네트워크 오버헤드가 증가할 수 있음
  • 복구가 어려움: 분산 트랜젝션 실패 시 모든 시스템에서 일관된 상태로 롤백하는 것이 어려울 수 있음

3-2. 이벤트 소싱

데이터 상태 변화를 이벤트로 기록하고 해당 이벤트들을 순차적으로 재생해 현 상태를 파악하는 방법
복잡한 비즈니스 로직을 수행하는 시스템에서 데이터 일관성과 추적 가능성을 높이는 데 유용함
복잡성이 증가할 수 있기 때문에 시스템 요구사항에 따라 신중하게 적용할 것

주요 개념

  • 이벤트: 데이터의 상태 변화를 나타내는 기록
  • 이벤트 스토어: 이벤트를 저장하는 저장소. 이벤트를 순서대로 저장
  • 에그리게이트(Aggregate): 관련 이벤트를 모아 현재 상태를 재현할 수 있는 엔터티
    • 도메인 모델의 일부분으로 이벤트를 적용해 상태를 변화시킴
  • 커맨드: 에그리게이트에 특정 동작을 지시하는 명령어. 이벤트를 생성하는 트리거
  • 프로젝션(Projection): 이벤트를 읽기 모델로 변환해 조회 성능을 최적화하는 방식
    • 이벤트를 기반으로 읽기 전용 데이터베이스를 업데이트함

장점

  • 데이터 변경 이력 추적에 용이
    • 모든 상태 변화를 이벤트로 기록하기 때문에 데이터 변경 이력을 완벽 추적할 수 있음
  • 복구 및 재생
    • 이벤트를 재생해 시스템의 현상태를 복구할 수 있음
    • 데이터 손실이나 시스템 장애 시 유용
  • CQRS와의 자연스러운 통합
    • 명령과 조회를 분리하여 성능과 확장성을 최적화할 수 있음

단점

  • 복잡성 증가
  • 읽기 성능
    • 이벤트를 재생해 현 상태를 계산해야 하므로 읽기 성능이 저하될 수 있음
    • 이를 위해 프로젝션과 CQRS를 활용할 수 있음

3-3. CQRS (Command Query Responsibility Segregation)

명령과 조회의 책임을 분리하는 소프트웨어 디자인 패턴
읽기 작업과 쓰기 작업을 서로 다른 모델로 분리하여 각 작업에 최적화된 구조를 사용할 수 있도록 함

주요 개념

  • 명령(Command)
    • 데이터를 변경하는 작업. 데이터베이스에 대한 쓰기 작업을 수행
    • 데이터의 상태 변경을 담당함.
    • 복잡한 비즈니스 로직을 포함할 수 있으며 데이터 무결성 보장을 위해 트랜젝션 사용
  • 조회(Query)
    • 데이터를 조회하는 작업. 데이터베이스에 대한 읽기 작업을 수행
    • 조회 모델은 읽기 전용 데이터베이스 또는 캐시를 사용해 빠른 응답을 제공

장점

  • 성능 향상: 읽기, 쓰기 작업 분리로 각 작업에 최적화된 데이터 저장소와 인프라 사용
  • 확장성: 읽기, 쓰기를 독립적으로 확장할 수 있음
    • 읽기 요청이 많은 경우 조회 모델을 수평 확장하여 부하를 분한하는 등
  • 유지보수성: 비즈니스 로직이 명령 모델에 집중되기 때문에 복잡한 상태 변경 로직 관리가 쉬움
  • 데이터 일관성: 이벤트 소싱을 통해 상태 변경을 이벤트로 기록하고 이벤트 재생으로 현상태 유지가 가능

단점

  • 복잡성 증가: 시스템 설계와 구현의 복잡성이 증가. 명령 모델과 조회 모델을 각각 설계, 관리해야 함
  • 데이터 동기화: 명령 모델과 조회 모델간의 데이터 동기화를 위해 추가적인 구현과 관리가 필요함

4. 모니터링과 로깅

시스템 안정성 유지, 성능 최적화, 문제 예방 및 대응을 위해 필수

4-1. 모니터링

애플리케이션, DB, 캐시 등 각 컴포넌트의 성능을 모니터링
Prometheus, Grafana 등의 도구 이용
시스템 주요 지표(TPS, 응답 시간, 에러발생률)를 모니터링하고 이상 징후 감지 시 알림 받을 수 있음

주요 사항

  • 실시간 상태 파악
  • 자동 알림: 특정 임계치 초과 시 알림 받을 수 있음
  • 성능 분석: 모니터링 데이터를 기반으로 시스템 성능 분석이 가능
  • 병목 지점 파악
  • 사전 예방
  • 신속 대응 가능

4-2. 로깅

주요 이벤트 로깅으로 문제 발생 시 원인 추적이 가능
Elasticsearch, Logstash, Kibana 등을 사용해 수집, 저장, 분석할 수 있음
이를 기반으로 문제 발생 시 문제를 파악하고 해결하는 데 이용

주요 사항

  • 이벤트 추적
  • 디버깅 및 오류 해결
  • 패턴 분석: 로그 데이터를 분석하여 사용자의 행동 패턴이나 시스템 성능 패턴을 이해할 ㅅ ㅜ있음
  • 장기적 최적화: 로그 데이터를 장기적으로 분석해 최적화를 진행할 수 있음
  • 문제 원인 분석
  • 법적 및 규제 요구사항 준수: 법적으로 보관해야만 하는 데이터가 있음

5. 테스트와 배포

어디에서나 테스트와 배포는 중요하다.
일단 멀쩡히 잘 굴러가는지 확인해야 하고, 또 멀쩡히 잘 굴러가야 하기 때문이다.

5-1. 테스트

이전에 공부한 내용.
테스트코드 작성하기 / 테스트

간단하게 정리해보았다.

  • 단위 테스트
    • 시스템 개별 구성요소를 테스트. JUnit, TestNG 등의 도구로 자동화된 단위 테스트를 작성하고 실행
    • 개발 초기 단계에서 발생할 수 있는 결함을 조기에 처리하는 데 유용함
  • 통합 테스트
    • 여러 구성 요소가 함께 동작하는 지를 테스트. 개별 구성요소의 상호작용 테스트
    • @SpringBootTest 어노테이션 활용
    • 인터페이스 간의 문제를 발견하는 데에 유용함
  • 부하 테스트
    • 시스템이 높은 트래픽 상황에서도 문제없이 돌아가는지 확인. Apache, JMeter 등의 도구 활용
    • 시스템 성능 한계를 파악하고 병목 지점을 찾아 최적화 할 수 있음
  • 회귀 테스트
    • 새로운 코드 변경이 기존 기능에 영향을 미치지 않는지 확인
    • 기존 테스트케이스를 자동화해 주기적으로 실행하며 코드 변경으로 인한 결함을 방지할 수 있음
  • 사용자 수용 테스트
    • 실제 사용자 환경에서 시스템을 테스트해 사용자가 요구하는 기능이 모두 제대로 동작하는지 확인
    • 사용자 피드백 반영으로 시스템 최종 조정을 마치면 배포 준비 완료
    • 시스템이 실제 운영 환경에서 기대한대로 동작하는지 확인하는 단계

5-2. CI/CD

지속적인 통합(CI, Continuous Integration)

  • 변경 코드를 자주, 자동으로 빌드, 테스트하며 코드 변경 시점에서 발생할 수 있는 문제를 조기 발견, 해결함
  • 개발 주기 단축, 코드 품질 향상의 이점

지속적인 배포(CD, Continuous Deployment)

  • CI 파이프라인을 통해 검증한 코드를 자동으로 프로덕션 환경에 배포
  • 코드 변경 사항을 빠르고 안전하게 프로덕션 환경에 적용하며, 새로운 기능을 신속하게 제공할 수 있음

Canary 배포

  • 새로운 버전을 전체 시스템에 배포하기 이전에 일부 사용자에게만 배포하여 문제가 없는지 체크
  • 문제 발생 시 빠르게 롤백
  • 리스크를 최소화하면서 새로운 기능을 단계적으로 도입할 수 있는 방법

블루-그린 배포(Blue-Green Deployment)

  • 두 개의 환경을 사용하여 하나는 현재 운영 중인 환경, 하나는 새로운 버전을 배포하는 환경으로 사용
  • 새로운 버전을 그린 환경에 배포한 후, 모든 트래픽을 그린으로 전환해버림
  • 문제 발생 시 블루 환경으로 롤백
  • 무중단 배포를 가능케하며 배포 실패 시 신속한 복구 제공

롤링 배포(Rolling Deployment)

  • 새로운 버전을 점진적으로 배포하여 각 서버를 순차적으로 업데이트함
  • 시스템 가동 시간을 유지하며 점진적으로 새로운 버전을 도입할 수 있음
  • 대규모시스템에서 무중단 배포를 구현하는 데 유용함

RabbitMQ

메시지 브로커
애플리케이션과 시스템 간에 메시지를 송수신하는 데 사용
메시지 큐(Message Queue)를 기반으로 하며, 주로 비동기 통신, 시스템 간 데이터 전달, 이벤트 기반 아키텍처를 구현하는 데 사용됨

역할

  • 비동기처리
    • 데이터를 비동기적으로 처리해 시스템의 응답성을 높임
  • 부하 분산
    • 여러 소비자에게 메시지를 분산시켜 시스템의 부하를 균형 있게 분산함
  • 내결함성
    • 메시지를 안전하게 저장하여 시스템 장애 시 데이터 손실을 방지함

주요 개념

  1. 메시지 브로커
    • 메시지 생산자(producer)가 보낸 메시지를 받아 저장한 후, 이를 소비자(consumer)에게 전달
    • 메시지의 신뢰성과 순서를 보장함
  2. AMQP (Advanced Message Queuing Protocol)
    • AMQP 0-9-1 프로토콜 지원
    • AMQP는 메시지 브로커와 클라이언트 간의 통신 규칙을 정의하는 표준 프로토콜
  3. 메시지 큐(Message Queue)
    • 메시지를 queue에 보관
    • 여러 consumer가 큐에서 메시지를 가져가 처리할 수 있음

주요 구성 요소

  1. Message: 전달되는 데이터 단위.
  2. Producer: 메시지를 생성하여 RabbitMQ로 전송.
  3. Exchange: 메시지를 큐에 라우팅함. 라우팅 방식은 Exchange 유형에 따라 달라짐.
    • Direct: 특정 라우팅 키를 사용하는 메시지를 정해진 큐로 보냄.
    • Fanout: 메시지를 모든 큐로 브로드캐스트.
    • Topic: 패턴 매칭으로 메시지를 라우팅.
    • Headers: 메시지 헤더의 특정 속성을 기반으로 라우팅.
  4. Queue: 메시지를 저장하는 버퍼. 메시지가 Consumer에 의해 처리될 때까지 대기.
  5. Consumer: 큐에서 메시지를 가져와 처리하는 역할.
  6. Binding: Exchange와 Queue 간의 연결을 정의함. Exchange에 메시지가 도착했을 때, 특정 Queue로 라우팅되도록 설정.

RabbitMQ의 주요 특징

  1. 유연성
    • 다양한 메시지 패턴 지원: 여러 메시지 전달 패턴(단일 소비자, 다중 소비자, 라운드 로빈, 팬아웃 등)을 지원
    • 다양한 프로토콜 지원: AMQP, MQTT, STOMP, HTTP 등을 지원
  2. 메시지 신뢰성
    • 메시지 지속성(Durability), 확인(Acknowledgment), 복제(Replication)를 통해 메시지 유실을 방지
  3. 확장성
    • 클러스터링을 통해 확장 가능. 여러 노드에서 메시지를 분산 처리할 수 있음
    • 분산 아키텍처: 페더레이션, 셰어드 노딩을 통해 분산된 메시징 시스템을 구축할 수 있음
  4. 플러그인 지원
    • RabbitMQ는 다양한 플러그인을 통해 인증, 모니터링, 메시지 TTL(Time-To-Live) 설정 등을 지원
  5. 관리 인터페이스
    • 웹 기반 관리 대시보드를 제공하여 큐, 메시지, 연결 상태를 모니터링하고 관리할 수 있음

장단점

장점

  • 다양한 언어와 프로토콜 지원
  • 메시지 신뢰성을 보장함
  • 플러그인을 통한 확장성

단점

  • 러닝커브 !!!!!
  • 설정 및 운영 복잡성
    • 복잡한 설정: 초기 설정이 복잡할 수 있으며 클러스터링 및 분산 환경에서는 더 많은 설정 요구됨
  • 성능 이슈
    • 메시지 브로커 오버헤드: 모든 메시지를 중앙 브로커를 통해 전달하기 때문에 높은 트래픽 상황에서는 오버헤드가 발생할 수 있음
    • 대량의 메시지 처리에서는 성능 이슈가 있을 수 있음(Kafka 등과 비교할 때)
  • 운영 비용
    • 리소스 소비: 메모리와 CPU 자원을 많이 먹을 수 있음. 충분한 리소스를 제공해야 함
    • 모니터링 및 유지보수: 지속적인 모니터링과 유지보수가 필요함.
  • 제한된 메시지 크기
    • 메시지 크기 제한: 매우 큰 메시지 처리에는 제한이 있을 수 있음. 대용량 파일 전송에는 적합하지 않음

AMQP

메시지 지향 미들웨어(MOM, Message-Oriented Middleware)에서 사용되는 애플리케이션 계층 프로토콜
메시지 송수신의 신뢰성과 보안을 보장

주요 개념

  • Message: 전송 데이터 단위
  • Queue: 메시지를 저장하고 전달
  • Exchange: 메시지를 큐에 라우팅
  • Binding: Exchange와 Queue 간의 연결을 정의

Exchange

메시지 브로커가 메시지를 교환기에서 큐로 라우팅하는 방식
다양한 방식으로 메시지를 라우팅할 수 있으며, 주로 메시지의 라우팅 키와 바인딩 키 또는 패턴을 기반으로 작동함

Direct Exchange
- 라우팅 키가 정확히 일치하는 큐로 메시지를 전달
- 라우팅 키가 a인 메시지를 a라는 바인딩 키를 가진 큐로 전달하는 식

Fanout: 메시지를 모든 큐로 브로드캐스트
- 라우팅 키를 무시하고 교환기에 바인딩된 모든 큐로 메시지를 브로드캐스트
- 모든 바인딩된 큐로 메시지가 전달됨

Topic Exchange: 패턴 매칭으로 메시지를 라우팅
- 패턴에는 와일드카드()와 #가 사용됨
- 라우팅 키가 quick.orange.rabbit인 메시지는 바인딩 키가
.orange.*인 큐로 전달되는 식

Headers Exchange: 메시지 헤더의 특정 속성을 기반으로 라우팅
- 라우팅 키 대신 메시지의 헤더를 기반으로 메시지를 라우팅함
- 헤더 값과 바인딩된 헤더 값이 일치하는 큐로 메시지를 전달

profile
고민고민고민

0개의 댓글