/ Dev

SNS 에 들어온 모든 Job 을 놓치지 않고 Lambda 와 SQS를 이용해 처리하는 방법

SNS로 초당 100건 이상의 꽤 많은 메시지가 들어오는 경우를 상상해봅니다. 그러한 서비스를 하고 있습니다. 이 모든 메시지를 단 한건도 놓치지 않고 모두 적절하게 처리를 해야 했고, 한 메시지당 처리속도는 5초에서 10초정도 걸리는 작업들이었습니다. 그래서 아래와 같은 구조를 가진 SNS, SQS, Lambda 를 설계하게 되었습니다.

sns-forever--2-

구조는 그리 복잡하지 않습니다. data-entry의 전송 정책에 실패시 재시도 규칙을 적절한 딜레이를 통해 걸고, 들어오는 모든 데이터를 data-entry-job Lambda 로 보냅니다. 만약 이 Lambda 가 실패한다면 몇초 후 다시 data-entry-job를 재시도하도록 설정을 해뒀습니다. 이렇게 해두면 서버에 장애가 발생하여 모든 Job 이 실패하더라도 빠른시간 이내에 복구가 된다면 실패하여 재시도를 기다리며 하늘에 둥둥 떠있던 Job 들이 1시간동안 재시도함으로써 모든 Job 이 성공에 도달할 수 있겠죠.

서버 이슈라는게 1시간만에 해결되지 않는 경우를 상상하지 않을 수 없습니다. 그런 경우를 대비해서, 모든 SNS 메시지를 SQS에도 담아둡니다. 문제가 생겼을 경우 Emergency Queue Listener를 가동하여 SQS에 쌓인 데이터들을 모두 data-entry-job으로 보내도록 하면 그동안 실행하지 못한 모든 Job 들을 실행할 수 있습니다. 과도한 SQS 요금을 내지 않기 위해서 이 SQS에 들어온 메시지는 별도로 처리하지 않으면 하루뒤에 자동으로 만료(=삭제)되도록 설정을 해뒀습니다.

SNS

우리가 처리해야할 대량의 메시지가 도착하는 곳입니다. 1초에 100개가 도착할 수도, 1000개가 도착할 수도 있다고 가정할 수 있습니다.

-----------2018-06-15-------5.50.16-1
메시지를 받으면 Lambda 와 비상용 SQS로 메시지를 포워딩하도록 설정해둡니다. Lambda 는 메시지를 받는 즉시 실행 시킬 것이고, SQS는 메시지를 잃어버렸을 경우에 다시 복구할 수 있도록 도와줄 것입니다.

-----------2018-06-15-------5.21.16-1
그 후에는 Lambda 의 실행이 실패했을 때의 정책을 설정해야합니다. 시스템 장애 상황을 상상하면서 어떻게 횟수를 정해야될지 상상해보세요. 옵션들에 대한 자세한 설명은 공식 메뉴얼에 있습니다. 재시도는 최대 1시간까지만 가능합니다. 1시간동안 계속해서 재시도 했지만 실패할 경우에는... 메시지는 영구히 사라집니다.

Lambda

이 구조에서 Lambda 는 각 메시지를 실행시켜 어떤 일을 할지 그 일을 프로그래밍 할 수 있게 합니다. 이 Lambda 를 작성할 때는 메시지 처리의 성공과 실패를 확실하게 구분하여 응답하도록 해야합니다. 실패를 인지할 수 있어야만 SNS에서 다시 재시도를 할 수 있기 때문입니다.

이전에 받았던 메시지를 또 받게 되는 중복 메시지 처리도 잘 해야합니다. 이렇게 될 경우 작업을 한번 더 하지 않고 그대로 Lambda 를 성공처리를 한다던지, 혹은 덮어쓴다던지 하는 개발이 필요합니다. 개발하고 계신 응용프로그램에 따라 다양한 상황이 있을 수 있으며 그 상황에 따라 적절히 개발하셔야합니다. 만약에 중복 메시지를 받았을 때 실패가 되면 무조건 재시도가 일어나겠죠.

-----------2018-06-15-------5.30.36-1 -----------2018-06-15-------5.30.50-1

로그를 디테일하게 찍을수록 수많은 Lambda 를 모니터링하기 쉬워집니다. CloudWatch 의 필터 기능을 이용하면 찍어둔 로그를 상당히 쉽게 가공하여 그래프화시켜 볼 수 있습니다. 원하는 수치들을 빠트림 없이 모니터링 할 수 있는데, 만약 5분동안 10만개의 Job 이 돌아가는 와중에 실패갯수가 2-3개 정도 된다면 그것마저도 캐치해낼 수 있습니다. 물론 비용이 드는 것은 어쩔 수 없습니다.

SQS

SQS는 이 구조에서 확실한 보험 역할을 하게 됩니다. Lambda 가 1시간동안 자동 재시도를 하다가 결국에는 실패했을 경우를 대비한 메시지 임시 저장소입니다. 얼마나 보관할지도 중요하고, FIFO를 쓸지 일반 대기열을 쓸지도 나름대로 중요합니다. FIFO SQS 대기열은 초당 횟수 제한이 걸려있습니다. 여러분들의 SNS의 Throughput 에 따라서 FIFO를 쓸지 일반 대기열을 쓸지 선택하시기 바랍니다.

-----------2018-06-15-------5.42.52-1
SQS의 설정은 크게 중요하진 않지만 메시지 보존 기간 옵션은 유용합니다. 이 옵션을 걸어놓지 않으면 SQS에 메시지가 무한정 쌓이게 됩니다. 비상시에만 쓸건데 요금이 낭비되죠. 적절하게 설정하는게 중요합니다. 또한 FIFO 대기열이 아니면 큐에서 메시지를 빼는 순서가 보장되지 않기 때문에, 과도하게 많은 메시지가 쌓인 상황이라면 비상시에 필요한 메시지만 꺼내 쓰기도 쉽지 않을 수 있으며 장애 대응 시간이 늘어날 수도 있습니다.