회사에서는 유저 행동에 대한 후처리 요청을 하는데 AWS의 SQS를 사용한다.
이미 입사했을때 SQS 설계가 다 되어있는 상태여서 초기 세팅은 알지 못했지만, 얼마 전 어떤 기능에서 메세지 전달관련하여 에러가 발생하는거 같아 조금 살펴보게 되었다.
결론적으론 SQS문제는 아니었고, 메세지를 전달받아 실행된 Lambda 프로젝트에서 KeyError 가 발생하여 병렬처리되는 Lambda가 불규칙적으로 중단되는 오류였다.
처음에 메세지 관련 문제일 것이라고 생각했던 이유가
1. 메세지 한개 전달 시 처리가 정상적으로 완료된다.
2. 메세지 두개 전달 시 처리가 정상적으로 완료된다.
3. 1과 2의 메세지 총 3개를 전달시 3개중 2개만 처리되고 하나는 처리중에서 무한대기 상태에 빠진다. (Lambda에서 Exception이 발생하여 남아있는 메세지를 미쳐 처리하지 못하게 된 상태)
위와 같은 문제가 발생하여 3개이상의 메세지 전달과정에서 오류가 있지 않았나 생각했었다. (결론은 아녔다..!!)
1. AWS의 메세징
AWS에서 제공하는 메세징 기능에는 SQS와 SNS가 있다. 흔히 Producer 로부터 메세지가 생성되어 메세징 서비스가 메세지를 전달받으면 이 내용을 Consumer에게 전달하여 작업이 처리되도록 한다. 이후 Consumer가 메세지를 생성하게 되면 메세징 서비스를 통해 Producer에게 다시 전달되기도 한다.
즉, 메세징 서비스는 요청한 곳과 요청을 받아 처리하는 곳의 전달자를 수행한다.
1) SQS (Simple Queue Service)
SQS는 Queue 기반 메세징 서비스로 선입선출 (FIFO) 로 메세지가 처리된다. 따라서 동시다발적으로 요청이 들어와도 요청 순서에 따라 순차적인 메세지 처리가 가능하다.
이러한 SQS는 한개의 Consumer에게만 메세지 전달이 가능하다.
만약 유저의 행동이 "구매" 와 "판매" 두가지 기능이 있다고 했을때, 이벤트 발생시 Lambda와 같은 프로젝트로 작업 처리 요청을 보내기 위해선 구매관련 SQS, 판매관련 SQS를 생성해야 한다.
이렇게 되면 구매와 판매 각각의 기능에 서로 병렬적으로 작업의 순차처리가 가능해진다.
ex)
구매1 -> 구매2 -> 판매1 -> 구매3 -> 판매2
위와 같은 유저 요청이 순차적으로 발생했다고 했을때 SQS가 한개에서 처리되었다면 요청들어온 순서대로 작업이 처리될 것이다.
하지만 구매와 판매의 SQS가 분리되어있기 때문에
구매 Queue : 구매1 -> 구매2 -> 구매3
판매 Queue : 판매1 -> 판매2
위와 같이 작업이 처리된다.
2) SNS (Simple Notification Service)
SNS역시 Consumer (구독자 라고 부르기도 한다) 에세 메세지를 전달하는 역활을 수행한다. 이때 Consumer는 Lambda와 같은 기능 뿐만이 아니라 SQS가 될수도 있고, 모바일이나 웹 자체에 알람을 보낼수도 있다.
SQS와 달리 SNS는 복수개의 Consumer를 가질 수 있다. 메세지 내용에 따라 서로 다른 Consumer에게로 메세지 전달이 가능하기 때문이다.
만약 위의 SQS예제에서 SNS를 사용하였다면 구매와 판매 각각의 메세징 서비스를 사용하지 않고, 발생하는 메세지는 모두 SNS로 보낸 다음 SNS에서 각각의 SQS로 메세지를 전달하여 최종적으로 요청이 처리되도록 구조를 설계할 수 있다.
이렇게 되면 SNS비용과 SQS비용이 모두 발생하기 때문에 한개의 SNS로 각 서비스에 요청을 처리하도록 하기도 한다.
2. 메세징 사용 이유
메세징 서비스는 기본적으로 비동기로 돌아간다. 때문에 작업 요청이 들어오고, 이 요청을 마무리 하기까지 시간이 오래걸리는 경우 작업 요청자는 결과가 나올때까지 기다려야 하는 과정이 없게 된다. (요청을 던지는 것이니까)
특정 조건에 대한 다량의 데이터를 조회하거나, 외부 api 를 호출하여 데이터를 가공하는 등과 같이 작업처리에 시간이 오래걸린다면 이러한 메세징 기반 서비스를 도입해 요청에 따른 처리를 비동기로 수행하게 하는것이 좋을 듯 하다.
물론 비동기로 처리하였을때 그 결과를 다시 확인하는건 필수..!!
(메시지 처리 결과를 요청을 처리한 곳에서 저장하도록 하고, 그 결과를 유저가 확인할 수 있다던가...)
+) 메세지 3개중 일부만 성공한 이유.. (파악중)
SQS, SNS와는 무관하지만 애초에 이 기능을 살펴보게 만든 이슈가 아직 의문이다.
해당 프로젝트는 Lambda로 구성되어있고, SQS로부터 전달받은 메세지는 특정 키 안에 list 형태로 되어있다. 어떤 요청을 처리하든지 공통 처리 부분에서 무조건 Key Error가 발생하게 되는데, 그렇다면 처음 요청에서 바로 에러가 발생해야 하는게 아닌가? 하는 생각을 하였다.
디버깅을 하면서 그 흐름을 따라가보니 정말로 첫번째 요청때도 KeyError가 발생하지만 이때에는 Exception이 일어나지 않고, 두번째 요청에서 또한번의 KeyError가 발생했을때 Exception이 발생한다.
'공부로그' 카테고리의 다른 글
[Python] 파이썬에서의 멀티쓰레드 작업과 GIL (0) | 2024.03.21 |
---|---|
플로이드-워셜 풀이가 궁금하다 : i와 j노드가 k로 연결되어있으면 i와 j도 연결되어있다. (0) | 2024.03.10 |
[Python] timedit 사용하여 자료형 변수 선언 방식 비교하기 : dict() vs {} (0) | 2024.02.01 |