Amazon Simple Notification Service(Amazon SNS)
Amazon Simple Notification Service(Amazon SNS)
- 주제 (topic) 생성
- 해당 하는 모든 구독자에게 메시지를 푸시
배경
카카오 알림톡 장애로 기부를 못하는 상황이 발생했습니다 당시 시니어 개발자는 장애가 발생되면 성장의 기회라고 말해주셨고 이 상황을 해결하기 위해서 비동기 프로그래밍 회의를 진행했었습니다
비동기 프로그래밍
비동기 프로그래밍은 여러 작업이 동시에 진행될 수 있도록 하여 각 작업이 다른 작업의 완료를 기다리지 않고 독립적으로 실행될 수 있게 하는 방식
SNS,SQS,KAFKA 중 어떤 기술을 쓸지 고민했었습니다
특징 | Kafka | SNS (Simple Notification Service) | SQS (Simple Queue Service) |
---|---|---|---|
유형 | 분산 스트리밍 플랫폼 | Pub/Sub 알림 서비스 | 분산 메시지 큐 |
주요 용도 | 실시간 데이터 스트리밍, 이벤트 소싱 | 알림 시스템, 이벤트 기반 처리 | 비동기 메시지 큐, 작업 대기열 관리 |
메시지 저장 | 메시지 영구 저장 (디스크에 저장) | 메시지 영구 저장되지 않음 | 메시지 저장 (최대 14일) |
확장성 | 매우 높은 확장성, 분산 처리 | 높은 확장성, 자동 스케일링 | 높은 확장성, 자동 스케일링 |
메시지 순서 | 메시지 순서 보장 가능 | 순서 보장 없음 | 순서 보장 가능 (FIFO 큐 사용 시) |
지속성 | 강력한 지속성 (디스크에 저장) | 없음 (메시지 전송 후 사라짐) | 메시지 지속성 있음 |
사용 용도 | 로그 수집, 스트리밍 데이터 처리, 이벤트 처리 | 실시간 알림, SMS/이메일/모바일 푸시 알림 | 분산 시스템에서 작업 큐 처리 |
속도 | 매우 빠르며 높은 처리량 지원 | 빠른 알림 전송, 지연 시간 짧음 | 상대적으로 느림 (동기/비동기 큐 처리) |
구독 옵션 | 여러 소비자가 독립적으로 구독 | 다양한 프로토콜을 통한 구독 (HTTP, Lambda, SQS 등) | SQS나 Lambda로 메시지 전달 가능 |
복잡성 | 상대적으로 설정과 운영이 복잡 | 간단한 설정과 사용 | 상대적으로 간단한 설정과 사용 |
메시지 크기 | 큰 메시지 처리 가능 (메시지 크기 제한 없음) | 최대 256KB | 최대 256KB |
작은 규모 서비스이고 결국 메시지 지속성 있고 상대적으로 간단한 설정과 사용방법으로 SQS 를 선택했었다 만약 SNS를 통해서 했더라면 어떨까?
SNS+SQS 를 사용했다면!
- 서비스에서 알림톡 발송을 위해 message+topic SNS 토픽에 메시지를 Publish
- SNS는 해당 메시지를 연결된 SQS 큐(kakao-message-queue)에 Push하여 전달
- 메시징 시스템 서비스는 SQS 큐를 Polling하여 메시지를 수신하고, 인포뱅크 API를 호출해 알림톡을 발송합니다
[발신 서비스]↓ (Publish)[SNS Topic: kakao-message-topic]↓ (Push)[SQS Queue: kakao-message-queue]↓ (Receive)[카카오 메시지 시스템 서비스]↓ (HTTP)[인포뱅크 발송 API]
SNS 만 사용했던 경험
- 여러 서비스가 log-topic 으로 메시지를 Publish
- Logging Service는 이 log-topic을 Subscribe구독
- 수신한 메시지를 DB에 저장
[Service A] [Service B] ↓ (Publish) ↓ (Publish)[ log-topic (Pub/Sub Topic) ] ↓[ Logging Service ] (Subscriber) ↓[ Database ]
실사용
AWS SNS 를 이용해 여러 서비스에서 TOPIC 과 메세지를 보내면 로깅 서비스에서 TOPIC 을 구독하고 있다가 새로 메세지를 읽고 staging DB 에 저장하고 있었습니다
생각보다 많은 데이터로 부하가 발생해 데이터 베이스 따로 관리중.. db에 로그를 넣으면 보기는 service_id로 api 추척도 가능하고 좋지만..
장점 DB에 들어가 있으면 서비스 ID나 키를 기준 으로 빠르게 추적 가능 (트러블슈팅 편리) 조회나 분석이 간편함 (쿼리 편의성)
단점 DB 부하가 높아지면 서비스 성능에 악영향 데이터량이 많을 경우 스토리지 비용 증가 로그성 데이터의 특성상 빈번한 Write로 인해 DB 성능 저하(로그 데이터는 쓰기가 매우 빈번 → 관계형 DB에는 비적합) -> 결국 데이터베이스 분리 관리중.. 로깅이 잘못된 오류로 급격하게 많아지자 sns 실패 등 발생 (로그 폭주 시 DB 성능이 저하 → SNS 메시지 처리 지연 및 실패 발생)
DB에 넣는게 맞을까? 다른 방법도 있을까?
- 실시간은 아니어도 짧은 시간 이내(수 초~수 분)에 추적
SNS → SQS (큐) → 로깅 서비스 → staging DB
순간적 부하를 SQS로 흡수 가능
- 관계형 DB가 아니라 대규모 쓰기 처리에 강한 스토리지에 로그를 저장
실시간 SNS → SQS 또는 Kinesis Data Stream → Logstash 또는 Fluentd → Elasticsearch → Kibana SNS → 로깅 서비스 → DynamoDB 또는 MongoDB
- 비용 및 부하를 최대한 절감하는 것이 목표라면 → 파일 기반 저장 + 배치 처리
SNS → 로깅 서비스 → S3 (또는 EFS) → 배치 잡 → staging DB