모종닷컴

SQS 중복 수신 이슈 본문

Programming

SQS 중복 수신 이슈

모종 2022. 12. 24. 23:04
반응형

SQS Standard Queue를 사용 중인데 동일한 메시지를 각 애플리케이션이 중복 수신된 적이 있습니다. 제가 생각한 것들이 맞다면 메시지는 중복 수신되지 않을 것 같았는데 이런 이슈가 왜 발생했는지 궁금하여 좀 찾아봤습니다. 

일단 생각했던 아키텍처를 그림으로 그려보면 아래와 같습니다. Queue에서 동시성 처리가 되어있다면 app1, app2, app3에서 동시에 요청하더라도 메시지1, 메시지2, 메시지3이 잘 분배가 되겠지라는 게 기본적으로 깔려있던 전제였습니다.

SQS 아키텍처

이제 SQS의 실제 아키텍처를 보면 아래와 같습니다. 큐라고 생각했던 모습과는 완벽하게 다른 형태입니다.

큐에 메시지 삽입

이제 SQS에 메시지를 적재하는 과정과 메시지의 라이플 사이클에 대한 설명을 이어나가도록 하겠습니다. 먼저 적재하는 과정을 표현하면 아래 그림과 같습니다. 메시지를 SQS에 적재하게 되면 무언가(?)에 의해 여러 대의 분산된 SQS Server들에 메시지가 저장됩니다.

큐로부터 메시지 수신

메시지를 받아오는 과정은 위와 반대로 보면 됩니다. 단 사용하는 Standard 큐의 경우 2번 메시지를 가져오는 과정에서 적재된 순서와 무관하게 임의의 메시지를 가져오게 됩니다. 적재 순서가 1, 2, 5라고 해도 임의 순서인 메시지인 2번 메시지를 가져올 수 있는 거죠. 이 순서가 만약 중요하다면 Standard 타입이 아닌 FIFO 타입을 사용하면 됩니다. (참고)

그리고 또 한가지 중요한 부분이 있는데 만약 1번 메시지를 가져가게 된다면 다른 SQS Server에 있는 1번 메시지를 다른 Message Receiver가 받지 않도록 메시지에 visibility timeout을 설정하게 됩니다. 간단하게 예시를 들어보자면 만약 visibility timeout이 5분이라고 가정하고 1번 메시지를 어떤 Receiver가 메시지를 폴링 했다면 다른 SQS Server에서는 1번 메시지에 대해서 5분 동안 Message Consumer(?)가 가져가지 않도록 처리합니다.

중복 수신 문제의 원인이지 않을까?

제가 이번에 겪었던 중복 수신도 바로 이 특성 때문인 것 같다고 생각이 듭니다. 일단 AWS에서 자랑하고 있는 부분 중 하나가 Standard 타입은 메시지 처리량이 무한이라고 합니다. 메시지 순서를 유지할 필요도 없으니 무지성(?)으로 그저 아무 SQS Server에 메시지 하나만 달랑 가져오면 되는 거죠. 트랜잭션이라던지 동시성 처리도 하지 않았을 테니 처리량이 무한이 될 수 있지 않은 걸까 생각합니다. 

아무튼 핵심은 메시지를 가져가고 다른 SQS 서버에 visibility timeout을 설정하는 순간에 다시 한번 요청이 들어왔고 visibility timeout을 설정하지 않은 SQS 서버로부터 중복된 메시지를 가져오게 된 것 같습니다

중복메시지를 수신받은 시간대도 보니 거의 0.001초 차이도 나지 않았던 걸로 보아 문제의 원인은 이런 부분이지 않을까 한 번 생각해 봤습니다. 아무튼 SQS를 쓰게 된다면 이런 특성이 존재하니 더블 체크 겸 애플리케이션에서도 분산 Lock 등을 고민해봐야 하지 않을까요

반응형