[AWS] SNS 로 인한 람다 동시성 문제 해결
이전에는 SNS에서 발생한 이벤트가 Lambda를 직접 트리거하는 방식으로 구성되었습니다. 하지만 이 방식은 트래픽 급증이나 Lambda 동시 실행 제한으로 인해 이벤트가 처리되지 않거나 누락되는 문제가 발생할 수 있었습니다. 이를 해결하기 위해 SNS가 SQS 대기열을 통해 Lambda를 호출하도록 변경하면서 안정성과 확장성을 모두 확보할 수 있습니다.
1. 기존 구조: SNS -> Lambda
동작 방식
- SNS는 이벤트가 발생하면 메시지를 Lambda에 즉시 전달(푸시)합니다.
- Lambda는 메시지를 받아 처리하며, 처리 결과를 반환합니다.
문제점
- 동시 실행 제한
- Lambda 함수에는 AWS 계정당 기본 동시 실행 제한(1,000)이 있습니다.
- SNS가 이를 초과하는 메시지를 발행하면 초과된 메시지는 처리되지 않고 누락됩니다.
- 메시지 재처리 부족
- Lambda가 실패하면 SNS는 최대 4번의 재시도를 시도하지만, 여전히 처리되지 않으면 메시지가 손실됩니다.
- 트래픽 급증 처리 불가
- 트래픽이 급증하는 환경에서는 SNS가 Lambda의 처리 능력을 초과하는 메시지를 보내도 대기하거나 저장할 공간이 없습니다.
2. 개선된 구조: SNS -> SQS -> Lambda
변경 내용
SNS가 Lambda를 직접 호출하지 않고, 먼저 SQS 대기열에 메시지를 저장한 뒤 Lambda가 대기열에서 메시지를 하나씩 처리하도록 변경합니다.
동작 방식
- SNS -> SQS
- SNS는 이벤트가 발생하면 메시지를 SQS 대기열로 보냅니다.
- SQS는 메시지를 보존하며, 처리 가능할 때까지 저장합니다.
- SQS -> Lambda
- Lambda는 SQS 대기열에서 메시지를 하나씩 가져와 처리합니다.
- SQS의 메시지 보존 및 재시도 메커니즘 덕분에 Lambda의 동시성 제한 문제를 피할 수 있습니다.
3. 개선된 구조의 장점
3.1. 동시성 문제 해결
- SQS는 메시지를 큐에 저장하므로 Lambda의 동시성 제한(1,000)을 초과하는 메시지가 발생해도 안전하게 보존됩니다.
- Lambda는 제한된 수의 메시지만 처리하며, 나머지 메시지는 대기열에서 차례로 처리됩니다.
3.2. 메시지 보존 및 재처리
- SQS는 메시지를 최대 14일까지 저장할 수 있으며, Lambda가 메시지를 처리하지 못하면 재시도가 가능합니다.
- 메시지가 소비되지 않으면 Dead Letter Queue(DLQ)로 이동해 손실을 방지할 수 있습니다.
33. 확장성 및 안정성
- SQS는 트래픽 급증 상황에서도 무제한으로 메시지를 저장할 수 있으므로, 시스템이 높은 트래픽을 안정적으로 처리할 수 있습니다.
- Lambda와 SQS 간의 느슨한 결합 구조로 서비스 확장성이 높아집니다.
4. 구현 방법
CloudFormation을 활용한 구성
...
Resources:
UpdateKeywordSNSTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: UpdateKeywordSNSTopic
UpdateKeywordSQSQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: UpdateKeywordQueue
UpdateKeywordSubscription:
Type: AWS::SNS::Subscription
Properties:
TopicArn: !Ref UpdateKeywordSNSTopic
Protocol: sqs
Endpoint: !GetAtt UpdateKeywordSQSQueue.Arn
UpdateKeywordSQSQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- !Ref UpdateKeywordSQSQueue
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal: "*"
Action: "sqs:SendMessage"
Resource: !GetAtt UpdateKeywordSQSQueue.Arn
Condition:
ArnEquals:
aws:SourceArn: !Ref UpdateKeywordSNSTopic
UpdateTbProductFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: updatetbproduct/
Handler: app.lambda_handler
Runtime: python3.11
MemorySize: 4096
Events:
SQSTrigger:
Type: SQS
Properties:
Queue: !Ref UpdateKeywordSQSQueue
5. 주요 설정
- SNS와 SQS 연결:
- SNS 주제(
UpdateKeywordSNSTopic
)가 SQS 대기열(UpdateKeywordSQSQueue
)에 메시지를 게시할 수 있도록 SQS 정책(UpdateKeywordSQSQueuePolicy
)을 설정.
- SNS 주제(
- Lambda와 SQS 연결:
- Lambda 함수(
UpdateTbProductFunction
)가 SQS 대기열을 폴링하여 메시지를 처리하도록 설정.
- Lambda 함수(
- Dead Letter Queue 설정(옵션):
- 메시지가 처리되지 못할 경우를 대비하여 SQS에 DLQ를 추가로 설정할 수 있습니다.
6. 결과
변경 전
- SNS가 Lambda를 직접 호출하던 구조는 동시 실행 제한 초과, 메시지 손실, 트래픽 급증 시 안정성 부족 등의 문제가 있었습니다.
변경 후
- SNS가 SQS 대기열에 메시지를 저장하고, Lambda가 이를 처리함으로써 동시성 제한 문제를 해결하고 안정성을 확보했습니다.
- 메시지는 SQS에 안전하게 보관되며, 필요하면 재처리하거나 DLQ를 활용해 손실을 방지할 수 있습니다.
결론
SNS에서 Lambda를 직접 호출하는 구조는 간단하지만, 대규모 트래픽 처리나 안정성이 요구되는 경우 한계가 명확합니다. SQS를 중간에 추가하는 간단한 변경으로 메시지 보존, 동시성 제한 극복, 트래픽 급증에 대한 대응 등 다양한 문제를 해결할 수 있습니다.
댓글남기기