Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EDA 구조 고민, SNS + SQS 조합 분석 #58

Closed
ecsimsw opened this issue Nov 18, 2024 · 1 comment
Closed

EDA 구조 고민, SNS + SQS 조합 분석 #58

ecsimsw opened this issue Nov 18, 2024 · 1 comment

Comments

@ecsimsw
Copy link
Owner

ecsimsw commented Nov 18, 2024

요구 사항

  • 플랫폼에서 발생하는 이벤트를 처리하는 구조 고민이 필요합니다.
  • Kafka의 높은 인프라 비용과 운영/관리 러닝 커브에 따라, Kafka를 대체하여 팀에 보다 적합한 Event broker를 찾습니다.

SNS + SQS 구성 분석

  • SNS : 메시지 수신, 엔드 포인트 발산
  • SQS : 전통적인 메시지 큐, 이벤트 보관, 재시도, DLQ 처리 등
  • 기존 이벤트를 N일간 보관하고 Consumer에서 topic으로 수신하는 Kafka와 달리,
  • SNS를 이벤트 전달기로, 수신 실패시 재시도/임시 보관을 위한 MQ로 SQS를 사용하는 구조입니다.

카프카와의 비교 : 비용 측면

  • SNS는 비용이 들지 않습니다.
  • SQS의 경우 요청 1백만 개당 $0.5으로, 월에 1억개의 요청을 가정하면 7만원입니다.
  • 한 요청 안에는 1~10개의 메시지가 전달됩니다.
  • AWS의 매니지드 카프카, MSK의 경우 m7g.large(2cpu, 8GiB)가 시간당 $0.26으로, 클러스터 구성을 위해선 최소 50만원의 비용이 발생합니다.

Http 직접 전달과의 비교 1 : 인프라 관리 용이성

  • 인프라 관리의 용이를 위해선 Http로 직접 전달하는 방식이 가장 편할 것 같습니다.
  • 러닝 커브도 없고, 비용을 고민하지 않아도 됩니다.
  • SNS+SQS 조합은 프로젝트(마이크로 서비스)마다 SNS 토픽 지정, SQS를 설정이 필요합니다.

Http 직접 전달과의 비교 2 : 이벤트 유실과 의존 분리 측면

  • 이벤트 유실 문제에선 큰 강점을 갖고 있습니다.
  • SQS의 메시지를 소비하는 도중 예외가 발생하는 경우 재시도 처리, DLQ가 존재하기 때문에 이벤트 유실 가능성이 매우 적습니다.
  • 또한 서비스간 의존이 불필요해집니다.
  • 만약 Http 직접 전달로 이벤트를 처리한다면, 전달 서버에선 이벤트를 전달할 서버 정보를 모두 알고 있어야 합니다.
  • 반면, 큐를 사용하는 경우에는 수신 서버가 재가동되면 큐에서 메시지를 수신해 조금 늦은 알림을 전송할 수 있을 것입니다.

구현 난이도

  • Spring 프로젝트의 코드는 어렵지 않습니다. MQ Listener와 거의 동일한 코드 구성으로 이벤트를 수신합니다.
  • SNS과 Topic를 정의하고 SQS를 연결하는 인프라 구축은 비교적 간단합니다. (아래 테라폼 코드를 첨부해두었습니다)
  • 다만, 테라폼의 러닝 커브와 한번 생성된 자원을 장기적으로 유지/보수 하기 용이한가에 대한 고민은 필요해 보입니다.

Terraform AWS Provider 설정

provider "aws" {
region = "ap-northeast-2" # 서울 리전
}

SNS Topic 생성

resource "aws_sns_topic" "example_topic" {
name = "example-sns-topic"
}

SQS Queue 생성 (FIFO)

resource "aws_sqs_queue" "example_queue" {
name = "example-sqs-queue.fifo"
fifo_queue = true
content_based_deduplication = true
}

SNS와 SQS 연결 (Subscription 생성)

resource "aws_sns_topic_subscription" "example_subscription" {
topic_arn = aws_sns_topic.example_topic.arn
protocol = "sqs"
endpoint = aws_sqs_queue.example_queue.arn
}

보편적으로 사용되는 인프라 구성인가

  • 최근 많은 회사에서 Kafka 대신 SNS+SQS 조합으로 이벤트를 처리하는 꼴이 많아지고 있었습니다.
  • AWS 블로그에서도 자주 사용되는 조합이니만큼 참고할 수 있는 자료는 국내/국외로 충분해 보입니다.
  • 찾으면서 재밌었던 점은, Kafka의 운영 비용이나 관리 포인트를 모두 사용할 수 없는 스타트업/새 프로젝트에서 많이 도입되고 있었습니다.

우아한형제들 / 회원 시스템 이벤트기반 아키텍쳐 구축기

잡 코리아 / Kafka vs SNS+SQS 비교, 후자를 선택한 이유

인프런 / SNS-SQS 비동기 아키텍쳐

AWS / SNS + SQS 인프라 설정 방법, 테스트

@ecsimsw ecsimsw changed the title AWS 이벤트 처리 플랫폼 비교, SQS + SNS 조합 vs MSK 서비스 간 이벤트 전달 아키텍쳐 고민 Nov 26, 2024
@ecsimsw
Copy link
Owner Author

ecsimsw commented Dec 11, 2024

FIFO 타입과 Standard 타입

  1. FIFO 타입
  • FIFO 타입은 큐에 전달된 메시지를 완벽한 순서를 유지하여 처리합니다.
  • 큐에 있는 모든 메시지를 순서별로 처리하려고 하면, Consumer의 처리 속도에 따라 큐의 모든 메시지가 순차 처리되고, 처리 속도가 나오지 않을 것입니다.
  • 특히 메시지 처리 중 실패가 발생하는 경우, 다음 순서의 메시지가 처리되지 못하는 Stuck 상태가 발생하기 쉽습니다.
  • 이런 경우를 방지하고자 GroupId를 사용하여 순서를 유지할 메시지의 그룹을 정의합니다.
  • 같은 그룹끼리는 순서가 명확하게 정의되고, 서로 다른 그룹의 메시지는 순서와 처리 여부에 상관없이 처리되어 성능을 높입니다.
  1. Standard 타입
  • Standard 타입은 FIFO를 완벽하게 지키지 않습니다.
  • 그 덕에 여러 메시지가 순서에 상관없이 병렬 처리되어 성능상 이점이 있을 수 있습니다.
  • 다만, 메시지 처리 순서가 보장되지 않고, 중복 처리가 발생하기 좋습니다.

가시성 타임 아웃

  • SQS의 메시지가 Consume 된 이후에도 노출되면 여러 다른 Consumer에 의해 메시지가 중복해서 Consume되고, 이는 동일 메시지 중복 처리를 야기합니다.
  • 이를 막기 위해 SQS는 메시지가 Consume되고 처리하는 시간동안, 특정 기간동안 큐에 메시지를 노출하지 않도록 처리하여 중복 처리를 최소화하기 위해 노력합니다.
  • 가시성 타임 아웃이 끝났을 때까지도 메시지가 처리되지 못하면, 해당 메시지는 다시 큐에 노출되어 여러 컨슈머에서 시도할 수 있게되고, 이때는 다시 중복 처리가 발생할 수 있어 멱등성이 지켜지는 로직이 필요합니다.
  • 가시성 타임 아웃이 너무 길면, 메시지가 처리되지 못하고 지속되고 있는 상황이 발생할 수 있고,
  • 가시성 타임 아웃이 너무 짧으면, 메시지가 다 처리되지 못한채 다른 Consumer가 접근하여 중복 처리가 발생할 여지가 있습니다.

FIFO의 Deduplication ID

  • 중복 처리 문제는 수신 측에서 한 메시지를 여러번 Consume 하는 경우도 있지만, 반대로 Producer에서 여러번 동일한 메시지를 발행하는 경우에도 발생할 수 있습니다.
  • FIFO의 경우 Message 별로 Duplication ID를 관리하여 동일한 메시지의 경우 중복 발행되지 않도록 처리합니다.
  • FIFO의 Duplication ID는 메시지 본문을 해싱하여 생성되기에, 동일한 메시지 내용이면 Default 5분간 중복 발행되지 않습니다.
  • 반면 Standard의 경우, 높은 처리량을 우선으로 하여 Duplication ID를 지원하지 않고, message id는 발행된 메시지 별로 고유하여 메시지 중복 발행 검증에는 적합하지 않습니다.

고민 내용 1 : FIFO vs Standard

  • FIFO에서 처리량을 높이기 위해서, 특히 한 메시지 처리가 정상 수행되지 않아 이후 메시지가 모두 막히는 상황을 피하기 위해선 순서가 보장되어야만 하는 이벤트들의 Group 정의를 명확히 해야 합니다.
  • Standard에선 메시지 발행 시의 멱등성 처리와 메시지간 순서가 보장되지 않아도 되는지 확인해야 합니다.

고민 내용 2 : 중복 Consume 방지를 위한 멱등성 처리

  • Message 내용을 해시하거나, 발신 측에서 메시지에 CreatedAt를 넣어 메시지를 구분하는 것으로 중복을 막는 것도 방법일 것 같습니다.
  • 해시 값을 수신 측의 처리 결과를 저장하는 DB에 함께 저장하거나 Redis에 저장하여 일정 기간 동안 기록하여 Consume 하는 순간에 이미 처리된 메시지인지 확인합니다.

@ecsimsw ecsimsw changed the title 서비스 간 이벤트 전달 아키텍쳐 고민 EDA 구조 고민, SNS + SQS 조합 분석 Dec 11, 2024
@ecsimsw ecsimsw closed this as completed Dec 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant