Kafka vs RabbitMQ & MSA환경에 kafka를 적용한다면? (with 예제코드)

2024. 10. 26. 21:10·DevOps/devops

대규모 시스템이란

  • 방대한 양의 데이터를 처리하고 수 많은 사용자의 요청을 동시에 처리할 수 있는 시스템
  • 이러한 시스템 설계는 확장성, 유지보수성, 성능, 안정성 등을 고려
  • MSA 는 대규모 시스템 설계 아키텍쳐 패턴
  • RabbitMQ,Kafka 같은 메시징 시스템을 활용하여 각 서비스 간의 효율적인 데이터 통신과 확장성을 보장

메세징 시스템?

  • Queue 형태로 메세지를 저장. 송신자 (Producer)가 메세지를 큐에 넣으면, 수신자(Consumer)는 자신의 속도에 맞춰 Queue에서 메세지를 처리.
  • Message Broker를 사이에 두고, 송신자(Producer)와 수신자(Consumer)가 간접적으로 데이터를 주고 받음
  • MSA 환경에 적용한다면
    • 송신자 (Producer): MSA에서 메세지를 발행하는 곳 (e.g. 주문상태 변경에 대한 메세지를 order-msa에서 발행)
    • 수신자 (Consumer): MSA에서 메세지를 처리하는 곳 (e.g. 재고차감을 하기 위해 stock-msa에서 주문상태 변경 메세지를 수신)

기능

비동기 처리

Producer 메세지를 발행한 후, consumer가 메세지를 처리할 때까지 기다리지 않아도 됨 → 시스템의 유연성, 처리 효율성 ⬆️

 

데이터 손실 방지

데이터를 메세지 큐에 안전하게 보관. consumer가 메세지를 놓치지 않고 처리 가능 → 데이터 손실 방지, 신뢰성 있는 통신 보장

 

부하 분산

여러 consumer가 큐의 메세지를 가져가서 처리 → 시스템의 부하를 분산. 성능 ⬆️ 대용량 데이터를 처리할 때 유용

 

스케일링

메세지 큐 시스템은 수평적 확장이 용이. 더 많은 Producer, Consumer를 추가 가능 → 처리 능력 ⬆️

RabbitMQ vs Kafka

둘다 메세징 시스템이지만 어떤 점이 다를까?

RabbitMQ 구성도 (좌) Kafka 구성도 (우)

 

차이점 RabbitMQ Kafka
Producer ↔ Consumer의 상호작용 방식 Producer는 메세지를 보내고 메세지가 의도한 Consumer에 도착했는지 모니터링 → 우편물을 받아서, 수취인에게 배달하는 우체국 Producer는 Consumer가 메세지를 검색했는지에 대한 여부와 상관없이 Queue에 저장 → 다양한 장르의 메세지를 책장에 배치하는 도서관. 도서관 회원 (Consumer)가 책의 내용을 기억
아키텍쳐 - 복잡한 메시지 라우팅을 위해 설계
- 메세지큐 기반 설계
- push 모델 사용
- 더 복잡한 아키텍처를 사용. 처리량이 높은 스트림 이벤트를 관리
- 파디션 기반 설계 
- pull 모델 사용 
메세징 처리 방식 - 메시지 전달의 우선순위를 지정하는 범용 메세지 브로커
- 우선순위 대기열 지원
- 순서대로 메세지 처리
- Consumer가 메세지를 처리 → 브로커에 확인 (ACK) 응답 전송 → 브로커가 대기열에서 메시지 삭제 - 지연시간을 줄이고, 복잡한 메세지를 분산
- 우선순위 대기열 지원 X
- 토픽과 파티션을 사용하여 메세지 처리. 파티션 내부에서의 순서 보장 (offset)
- 메세지를 로그 파일에 추가. 보존기간이 만료될 때까지 보관. 로그파일에 있는 메세지는 언제든 데이터 처리 가능.
성능 - 초당 수천 개 메시지 처리 (그 이상은 다중 브로커 설정 필요)
- 지연시간이 짧다
- 초당 수백만 개의 메시지 처리
- 대용량 데이터를 처리한다
  • 어떤게 더 좋고 나쁜 것은 없다!
  • 구축하는 시스템의 요구사항에 더 적합한 것을 선택하는 것이 좋다. 

왜 MSA에서 쓰일까?

서비스간 비동기 통신

  • 서로 다른 서비스 간의 동기적인 호출이 많아지면 시스템 성능, 안정성에 영향
  • Kafka, RabbitMQ → 비동기 메시징을 통해 MSA간 통신을 비동기적으로 처리

확장성

  • MSA 환경에서는 증가하는 트래픽이나 데이터 양에 대응하여 성능을 유지시키거나 향상 시킬 수 있는 환경이 중요 합니다
  • Kafka → 파티셔닝 (수평적 확장), 클러스터에 브로커 추가 (다운타임 없이 추가 가능)
  • RabbitMQ → 클러스터링, 분산 큐

데이터 일관성, 신뢰성

  • 각 MSA는 독립적으로 데이터를 관리 (e.g. msa 별로 분리된 database 사용) → 서비스 간 데이터 일관성 유지 중요
  • Kafka → 로그, 메세지 저장 기능으로 데이터 일관성 유지, 메세지를 여러번 읽을 수 있도록 처리 가능
  • RabbitMQ → 메세지 디스크 저장, 다른 큐에 복제 하여 데이터 내구성 유지, 실패한 메세지 재처리 지원

서비스 간 결합도 ⬇️

  • Kafka → 이벤트 기반 아키텍처 지원. 서비스 간 독립적으로 동작 가능.
  • RabbitMQ → 큐 기반 메세징을 통해 서비스 간 메세지 전달.

✅ 요약  → RabbitMQ, Kafka는 MSA 에서 각각의 서비스가 독립적으로 동작하면서도 효율적으로 통신할 수록 지원하는 도구!

Kafka 를 MSA에 적용한다면

이벤트 중심 아키텍처 (Event-Driven Architecture)

  • 각 MSA간 통신을 이벤트 기반으로 처리. 통신을 담당하는 주체는 Kafka
  • 예시) 주문생성, 결제완료, 배송준비 등의 이벤트를 Kafka에 전달, 이를 구독하는 다른 서비스가 해당 이벤트를 처리하여 필요한 작업 수행

실시간 데이터 처리

  • 실시간으로 발생하는 대규모 데이터를 스트리밍 방식으로 처리
  • 예시) 사용자 행동로그, 모니터링 데이터를 실시간 분석 → 다른 서비스 전달

모니터링과 로깅

  • 중앙 집중식 로그 수집

이벤트 중심 아키텍처 Event-Driven Architecture 란

핵심 개념

이벤트

시스템 상태변화나 중요한 작업을 나타내는 객체. (e.g. OrderCreated, DeliveryCompleted)

 

이벤트 발행

MSA서비스에서 이벤트가 발생했을 때 (주문 생성 요청이 들어왔을 때), 해당 이벤트를 Kafka와 같은 메시징 시스템에 전달

 

이벤트 구독

  • 특정 이벤트에 관심 있는 MSA들이 해당 이벤트를 구독.
  • payment-msa는 order-msa가 발행한 OrderCreated 이벤트를 구독하고, 결제 처리 시작

비동기 처리

  • 이벤트를 발생한 MSA 서비스와 처리하는 MSA서비스가 비동기적으로 동작
  • order-msa는 OrderCreated 이벤트를 발행 후, 다른 MSA들이 처리하는 것을 기다리지 않고 (동기 X), 후에 필요한 비즈니스 로직 수행

코드 예시

build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
    implementation 'org.springframework.kafka:spring-kafka'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'

    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
        ...
}

application.yml

spring:
  application:
    name: order-msa
  datasource:
    url: jdbc:h2:mem:testdb
    driverClassName: org.h2.Driver
    username: sa
    password:
  h2:
    console:
      enabled: true
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  kafka:
    bootstrap-servers: localhost:9092
    consumer: # TODO kafka consumer, producer에 대한 설정값 수정은 여기에서
      group-id: ${spring.application.name}-group
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      properties:
        spring.json.trusted.packages: '*'
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringDeserializer
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8083

이벤트 발신

  • KafkaTemplate을 사용해서 이벤트를 발신.
  • 토픽과 보내고자 하는 이벤트 내용을 담아서 전송.
    • e.g. 배송시작 시 → DeliveryCreatedEvent를 생성해서 Notification-Msa가 관련 알림을 보낼수 있게 처리
@Service
@RequiredArgsConstructor
public class DeliveryService {
    private final DeliveryRepository deliveryRepository;
        private final KafkaTemplate<String, Object> kafkaTemplate; // 자동 주입

    @Transactional
    public void createDelivery(...) {
                Delivery delivery = new Delivery(...);
                deliveryRepository.save(delivery);

                DeliveryCreatedEvent event = new DeliveryCreatedEvent(...); //이벤트에 필요한 값을 넣어주세요
        kafkaTemplate.send("delivery-created", EventSerializer.serialize(event));
    }
}

이벤트 수신

  • @KafkaListener 를 사용하여 메세지를 수신
  • groupId는 application.yml에서 설정한 consumer group id 
@Transactional
@KafkaListener(topics = "delivery-created", groupId = "notification-group")
public void handleDeliveryCreatedEvent(String message) {
    DeliveryCreatedEvent event = EventSerializer.deserialize(message, DeliveryCreatedEvent.class);

    // 이벤트로 해야하는 후 처리 진행 (비즈니스 로직)
    // e.g. 배달완료 이벤트 발행 
}

Event-Driven + Kafka 구현 예시 

간단한 이벤트 중심 아키텍처를 맛(?) 볼수 있는 예제 코드 여기서 확인

예시 코드 구조

기술스택

  • Spring-Kafka
  • Kafka, Kafka-UI, Zookeeper, Zipkin
  • Spring Cloud-Discovery Client, Server, Gateway
  • Spring JPA
  • H2

이벤트 흐름

 

코드베이스에 포함된 것:

  • docker-compose.yml (zookeeper, kafka, kafka-ui, zipkin)
    • 실행이 안된다면, 환경변수를 설정해주세요! DOCKER_DEFAULT_PLATFORM=linux/amd64
  • 주문 생성, 주문 목록 조회 http 테스트 파일
  • order-msa, payment-msa, notification-msa skeleton 코드, gateway, eureka
  • 객체 Serialize, De-Serialize 유틸클래스

코드가 제대로 실행되고 있는지 확인 하는 방법

✅ docker-compose 실행 후 컨테이너 확인

 

✅ 모든 msa가 정상적으로 실행되는지 확인 → Eureka 대시보드 (http://localhost:8761)

 

✅ Kafka UI 에서 topic, consumer가 정상 등록되어있는지 확인

 

✅  api-test.http 파일을 통해 주문생성 API 실행. 각 Topic에서 메세지가 제대로 들어오는지 확인

  • 주문 → 결제완료 메세지
  • 결제 → 주문생성 메세지
  • 알림 → 주문완료

 

✅ notification-msa에서 주문완료 된 로그 메세지 출력 확인

  •  

더 알아보고 싶다면 🤓

이벤트 중심 아키텍처를 적용했을 때 msa에서 transaction 관리는 어떻게 하지?

  • Saga Pattern
  • Outbox Pattern 등등
  • 참고 자료
    • https://hudi.blog/saga-pattern/#코레오그래피-기반-사가-Choreography-based-Saga
    • Outbox Pattern → https://fullstackdeveloper.guru/2022/05/19/how-to-implement-transactional-outbox-design-pattern-in-spring-boot-microservices/

그 외, 읽어보면 좋은 글

  • https://techblog.woowahan.com/7835/
  • https://aws.amazon.com/ko/compare/the-difference-between-rabbitmq-and-kafka/
반응형
저작자표시 비영리 변경금지 (새창열림)

'DevOps > devops' 카테고리의 다른 글

[성능] heap dump 분석 툴 / heap dump analyzer  (0) 2022.09.20
[ubuntu] python을 찾을 수 없다고 할때  (0) 2021.03.18
서버에서 rm 커맨드가 없다고 할때 / rm command not found  (0) 2019.11.20
'DevOps/devops' 카테고리의 다른 글
  • [성능] heap dump 분석 툴 / heap dump analyzer
  • [ubuntu] python을 찾을 수 없다고 할때
  • 서버에서 rm 커맨드가 없다고 할때 / rm command not found
bandal-gom
bandal-gom
Devops & Backend Developer | tech blog
  • bandal-gom
    yayz's devlog
    bandal-gom
  • 전체
    오늘
    어제
    • 분류 전체보기 (68)
      • DevOps (22)
        • devops (4)
        • cicd (2)
        • docker (2)
        • monitoring (2)
        • nginx (4)
        • cache (1)
        • aws (1)
        • etc (6)
      • BE (21)
        • BE (3)
        • design pattern (1)
        • data structure (0)
        • spring (1)
        • algorithm (12)
      • devlog (24)
        • TIL (17)
        • programming language (2)
        • conference (2)
        • etc (3)
      • IT Review (1)
  • 블로그 메뉴

    • about.
    • 개발👩‍💻
    • etc.
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    algorithm
    프로그래머스
    키보드케이블
    알고리즘
    LeetCode
    문제풀이
    항해99
    homelab
    NGINX
    time complexity
    jenkins
    릿코드
    java
    티스토리챌린지
    노트북하기좋은카페
    Python
    til
    모각코
    Programmers
    array
    hash
    젠킨스
    leetcode 347
    오블완
    Kotlin
    알고리즘문제풀이
    개발자취업
    코딩테스트준비
    99클럽
    키캡
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
bandal-gom
Kafka vs RabbitMQ & MSA환경에 kafka를 적용한다면? (with 예제코드)
상단으로

티스토리툴바