WATCHA 푸시 서버 개선하기

Allan Bae
WATCHA
Published in
8 min readDec 4, 2020

--

WATCHA 푸시 서버 개선 사례를 공유합니다.

소개

안녕하세요. WATCHA에서 서버 개발을 하고 있는 Allan 입니다.
이번 포스팅은 WATCHA 푸시 서버를 개선한 사례에 대해 이야기를 해보고자 합니다.

개선전 푸시 서버

기존의 푸시 서버는 GORUSH 를 이용하여 왓챠, 왓챠피디아 각각 서비스 별로
따로 프로세스를 띄워 구동되고 있었습니다.

당시에도 큰 무리가 없이 쓰고 있었지만, 아래와 같은 개선이 요구되었습니다.

1. 푸시 발송에 관련된 로깅 및 분석

기존 푸시 서버는 따로 로그를 남기고 분석하고 있지 않았습니다. 그래서
어떤 유저에게 푸시를 전송했는지, 푸시받은 유저 행동은 어떠한지 … 등
푸시 관련된 유저에 대한 행동 분석이 어려운 상황이었습니다.
이러한 까닭에 적절한 로그수집 과 유저 행동에 대한 trace 필요했습니다.

2. 푸시 발송 제어

기존 푸시 서버는 푸시 요청 오는 즉시 푸시를 발송하는 형태 입니다.
이벤트성 푸시 경우와 같이 많은 푸시 요청이 푸시서버로 들어오는 경우
푸시가 특정시간에 몰려서 유저들에게 전달되어 순간적으로 많은 트래픽이
왓챠 또는 왓챠피디아 서비스로 유입되게 됩니다.

서버가 아주 넉넉히 유지 되는 상황에서는 큰 무리가 없을수도 있지만,
순간적으로 몰린 트래픽이 응답을 지연시키고 장애를 발생을 원인이 되곤 했습니다.
그래서 한번에 많은 푸시 발송전 미리 여유있게 서버를 증설해두거나,
푸시를 발송하는 각 서비스별 Client가 푸시 발송 지연 로직을 적용하여 푸시 서버로 발송을 요청하고 있었습니다.

이러한 불편함을 해결하기 위해서는 푸시서버가 발송 제어 로직 기반으로
푸시를 발송하여, 왓챠 또는 왓챠피디아 서비스 서버들이 적절히 Warming Up(Scale Out) 되도록 하는것이 필요 했습니다.

3. WebPush 와 같은 브라우저 푸시 및 커스텀 가능한 푸시 제공

좀더 세련된 형태의 푸시 메세지를 발송 할수 있고, 모바일 뿐만 아니라 웹(브라우저) 환경에서 많은 이용을 하고 있기 때문에, 웹(브라우저)환경에서 푸시 알림을 받을수 있도록 기능을 제공할 필요성이 있었습니다.

4. 각 서비스별 CLIENT 들이 손쉽게 푸시 발송을 요청

각 서비스별 Client 에서 사용하는 개발 언어에 상관 없이 쉽게 푸시를 발송할수 있고, 푸시 발송 스펙도 쉽게 이해하고, 활용할수 있는 구조가 필요 했습니다.

5. 서버 구조 변경 및 서버 지표 제공

기존 푸시 서버는 왓챠, 왓챠피디아 각각 푸시 서버를 서비스 별로 따로 띄워야 하고 트래픽 분산 및 Scale Out 이 되는 구조도 아니었습니다 .
게다가 실시간으로 서버 상태 및 푸시 발송수, 발송 성공, 발송 실패 … 등 유의미한 서버 지표를 매트릭으로 제공 할수 있는 기능도 제공하고 있지 않아서 운영 및 관리가 힘들 상황이었고, 개선이 필요 했습니다.

그래서 위와 같은 개선점을 적용한 신규 푸시 서버를 구축 하였습니다.
(프로젝트 이름은 HERA 이고 Golang 으로 구현되어 있습니다.)

개선된 푸시 서버

개선된 푸시 서버는 아래와 같습니다.

개선된 푸시 서버 구조

[개선] 1. 푸시 발송에 관련된 로깅 및 분석

우선 IOS 는 APNS, Android 는 FCM 을 이용하고 있는 구조에서 모든 디바이스가 FCM을 이용하는 형태로 변경하기로 했습니다.

모든 푸시 발송이 FCM(Firebase Cloud Messaging) 을 이용하게 되면
Firebase BigQuery Export 기능을 이용해서 푸시 발송 관련 로그들도 쉽게 BigQuery 로 전송이 가능합니다.
게다가 기존 App들도 Firebase SDK 이용하고 있어, App에서도 푸시 관련
이벤트 뿐만 아니라 다양한 이벤트들도 수집이 가능하여 푸시 발송 유저 행동에 대한 연관 분석이 가능합니다.

물론, 좀더 세밀한 분석을 위해서는 푸시 발송 성공유무, 발송된 푸시 종류, 타입 및 개별 유저에 대한 푸시를 식별하기 위한 MessageID…등 추가 정보가 필요했고,
추가적으로 푸시서버(Hera)에 발송시 필요 정보를 로그수집을 통하여 BigQuery 저장 하여 분석이 가능하도록 하였습니다.

푸시서버에서 로그수집은 이전에 포스팅 한 로그플랫폼을 통해 쉽게 수집하였습니다.

[개선] 2. 푸시 발송 제어

부하 분산을 위해 Client 에서 발송제어(delay)를 하게 되면, Client 별 따로 발송제어 로직을 가지게 되어 관리 이슈가 생기고, 서비스 측면에서 발송제어가 어렵습니다.
(개별 Client 별 제어만 가능)

그래서 각 Client는 발송제어 없이 무조건 요청하고, 실제 발송을 담당하는 푸시서버(Hera) 에서 푸시 발송 Rate Limiter 를 구현해 적용하여 발송제어를 하도록 하였습니다.

개략적인 Rate Limiter 동작 방식

Rate Limiter 구현은 간단히 구현 할수 있는 Time Window 방식을 이용했습니다.
Time Window 은 분당 생성되며, 각 Time Window 마다 발송제어 Limit가 존재합니다.

여러 푸시서버에서 Time Window 을 공유하고(Redis 를 이용), 각 푸시서버에서 푸시발송시 현재 발송하는 시점에 해당 하는 Time Window를 가져와 현재 발송 Limit 에 도달 했는지 확인 한 후 발송 또는 지연을 하게 됩니다.

그리고 TCP Congestion Control Policy(Tahoe, Reno … 등)와 같이 Slow Start 방식을 이용해, 특정 기간동안 발송 내역을 참고하여 발송 Limit 를 주기적으로 재조절 하는 로직 적용하여 Limit를 적절히 늘리거나 줄여서 발송 제어를 하게 됩니다.

Limit 에 도달 하여 발송 제한 되어 Pending 된 푸시 요청은 AWS SQS에 저장되어 추후 자동으로 발송되게 됩니다.

푸시 발송 브로커 구조

전반적인 푸시 발송 구조는 위 그림 처럼 Broker들이 처리 하도록 구현되어 있습니다.
각 푸시 요청은 메인 BrokerQueue에 들어가게 되고, Rate Limiter 의해서
발송 가능 상태면 FCM Broker 로, 발송 지연 상태이면 SQS Broker 로 가게 됩니다.

FCM Broker 로 전송된 메시지는 FCM을 통한 푸시 발송이 이뤄지고, SQS Broker 로 전송된 메시지는 SQS 에 enqueue 되고, 추후 발송이 이뤄지게 됩니다.

[개선] 3. WebPush 와 같은 브라우저 푸시 및 커스텀 가능한 푸시 제공

푸시서버(Hera)는 FCM 이 지원하는 WebPush 뿐 만아니라 커스텀 형태로
푸시메시지 전송 가능하도록 FCM 이 지원하는 API 및 구조를 그대로 포팅해서 구현되어 있습니다.
따라서 FCM V1 API 에서 제공하는 기능을 대부분 지원 하도록 구현 되어 있습니다.

[개선] 4. 각 서비스별 CLIENT 들이 손쉽게 푸시 발송을 요청

푸시서버(Hera)는 GRPC 기반으로 만들어져 있어서, 각 Client 가 이용하는 언어 따라 쉽게 사용할수 있도록 라이브러리 형태로 제공하고 있어서, 손쉽게 원하는 push가 전송가능하도록 되어 있습니다.

[개선] 5. 서버 구조 변경 및 서버 지표 제공

각 서비스 별 푸시 서버를 따로 띄우지 않고, 통합된 푸시 서버로 구현하여
서비스 상관 없이 해당 서비스에 대한 푸시를 발송이 가능합니다.

확장성 및 관리 측면 효율적으로 하기 위해서, AWS Elastic Beanstalk With ECS 기반의 Multi Container를 이용해서 운영하고 있습니다.

그리고 실시간으로 현재 Rate Limiter limit 값, Pending 된 푸시 메시지 수,
푸시 발송수(성공, 실패), 각종 서버 상태
…등을 모니터링 하기 위해서 Prometheus Metric Exporter를 구현하고 모니터링 플랫폼을 통해 수집하고 있습니다.

Metric 수집

이전에 포스팅한 로그플랫폼에서 제공하는 모니터링 플랫폼을 이용하여, 각 서버의 매트릭들을 수집 하고 있습니다.

결론

푸시 서버 개선에 대한 과정을 간략히 공유해 보았습니다.

로그수집을 통한 분석이 용이하게 하며, 각 서비스별로 발송 제어를 하여 각 서비스들이 큰 부담을 주지 않도록 개선하며, 확장성 및 관리 편리하도록 구조 변경 및 모니터링을 지원하고, 각 Client 들이 쉽게 사용할수 있도록 개선해 보았습니다.

물론 아직 미흡하고, 고민해볼 포인트가 많아 지속적으로 개선할 예정입니다.

긴 글 읽어주셔서 감사합니다.

--

--