안녕하세요, 보라입니다!
오늘은 대량 푸시 보내는 작업을 위한 메세지 큐 시스템 구축 과정에 대해 알아볼게요.
😊3월부터 합류하신 루빗의 낭만 백엔드 개발자 태진님의 도움을 200% 받아 작성했습니다😊
목표
- 대량의 푸시를 Main Server 영향 가지 않도록 [정해진 시간에, 따로, 안전하게] 보내기
: 유저 경험 최적화🔥
: DB 부하 줄여 비용 절감🔥
현재 문제 상황
: Main Server에서 [DB에게 무리한 데이터를 요청]하고 [무거운 로직을 메인서버에서 돌려] 사용자에게 푸시를 보내는 과정에서 부하가 발생하여, [비용이 들고] [유저 경험을 안좋게] 만든다.
문제점: [DB에게 무리한 데이터를 요청]
해결법: DB에게는 최대한 심플하게 데이터 요청
where절에 많은 요청 금지. 최대한 select만 해서 데이터 가져오고, 나머지 데이터 필터링은 (DB보다 값싼) 인스턴스 안에서 하자.
문제점: [무거운 로직을 메인서버에서 돌려]
해결법: 메인 서버가 아닌 Worker 서버에게 무거운 로직 실행하도록 넘긴다.
용어설명
Worker: 일하는 공간
Queue API Server: 작업 주문을 받는 공간, 주문서를 받고 워커에게 넘겨줌
SQS: 작업 메시지 담는 공간, 주문서를 모아 놓은 공간
Cron: 시간별로 처리하는 공간
솔루션 아키텍쳐
참고) Main Server에서는 요청이 들어오는대로 데이터 반환,업데이트가 필요한 API만을 담당한다.
- 구현해야 하는 기능은 정해진 시간에 대량의 푸시를 보내는 것인데, 이 작업을 Cron, Queue API Server, SQS, Worker를 이용해 구현한다.
1) Cron에서는 정해진 시간에 Queue API Server로 요청 트리거를 보낸다. (즉각 응답을 반환해야 하지만, 그 안에 유의미한 반환값이 있을 필요는 없다. Worker에서 비동기로 작업이 진행되기 때문에, 응답은 대충 성공했다고 반환하기만 하면 된다.)
2) Queue API Server 내, 각 API에서는 큐에 요청을 적재하는 작업을 한다.
3) 큐 서비스는 AWS에서 제공하는 SQS(Simple Queue Service)를 사용한다.
4) Worker는 SQS를 구독하고 있다. 큐에 요청이 적재되는 순간, 이를 캐치해서 해당 요청을 진행할 수 있다.
5) Worker에서는 대량의 푸시 보내기 작업을 진행한다. (Main Server가 아닌 Worker에서.)
6) 대량의 푸시를 보내기 위해서는 User의 정보를 가져와야 하므로, RDS(Relational Database Service)에게 요청한다. 이 때, where절은 최대한 생략하고 select만 해서 심플하게 가져온다.
7) 가져온 User에서 탈퇴유저 제외, 푸시를 활성화 한 사람들 제외 등등의 필터링을 Worker에서 진행한다. Push 보내기도 마찬가지로 Worker에서 진행한다.
8) [더 나아가기] Push를 보내는 인스턴스도 따로 만들어서, 관심사를 분리할 수도 있다. 7에서 Push 보내는 작업을 Worker가 아닌 전용 Push서버에서 진행하는 것이다. (아키텍쳐 우하단에 회색박스로 가린 부분!)
요약하자면, 무거운 비동기 로직은 Main Server 가 아닌, Worker에게 맡긴다는 것이다!
👍Good
- 유저 경험 최적화🔥
: Worker에서 문제가 생겨도 Main Server에 영향 가지 않는다. (마이크로 서비스)
: 무거운 비동기 로직을 Worker에서 전담한다.
- DB 부하 줄여 비용 절감🔥
: 꼭 필요한 select문만 최대한 활용하여, 값비싼 DB에게 일을 시키지 않는다.
: SQS 설계 목적 중 하나는 아니지만, 루빗 서비스에 도움이 되어 적었다.
⚠️Worker 주의
- 큐에 걸맞는 작업만 받아서 처리한다.
: 큐에 적재하여 비동기로 처리해도 되는 로직들만 요청 보내자!
SQS란?
완전 관리형 메세지 대기열.
- 초기 비용 없이 소프트웨어를 관리하거나 인프라를 유지하지 않고 오버헤드를 제거할 수 있습니다.
: AWS가 제공하는 SQS 사용 -> 비용절감
- 메시지를 누락하거나 다른 서비스를 가용 상태로 유지하지 않고도 처리량에 관계 없이 대량 데이터를 안정적으로 전송할 수 있습니다.
: 메인서버 내에서 동작하지 않고 아예 따로 관리하여 안정적 전송
- 민감한 데이터를 애플리케이션 간에 안전하게 전송하고 AWS Key Management를 사용하여 키를 중앙 집중식으로 관리할 수 있습니다.
: 민감한 데이터는 AWS에서 중앙 집중 관리
- 사용량에 따라 탄력적이고 비용 효율적으로 확장할 수 있으므로 용량 계획 및 사전 프로비저닝에 대해 걱정할 필요가 없습니다.
: 사용량에 따라 AWS에서 쉽게 관리하게 해줌. 미리 걱정X
Etc: RabbitMQ, Kafka
- RabbitMQ: 소비자의 확인 메세지를 보장 (ex. 티모바일 등)
- Kafka: 높은 처리량이 장점으로, 데이터 스트리밍 서버에 적합 (ex. 카카오, 라인, 넷플릭스 등)
- SQS 이외에도 RabbitMQ, Kafka도 구축할 수 있지만, 우리 서비스 단에서는 구축과 관리가 쉬운 SQS로 충분하다!
- 루빗에서 RabbitMQ나 Kafka를 구현해보는 날도 오겠지!
이제 루빗 유저에게 다시 푸시를 보낼 수 있게 되었습니다.
리텐션 올려보자고요! 🔥🔥🔥