Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

karrot-0010: Push Notification 서비스 구현 분석 #18

Open
hello-yoochul opened this issue Apr 16, 2023 · 6 comments
Open

karrot-0010: Push Notification 서비스 구현 분석 #18

hello-yoochul opened this issue Apr 16, 2023 · 6 comments
Assignees
Labels
Analysis Doc Improvements or additions to documentation

Comments

@hello-yoochul
Copy link
Contributor

푸시 알림 서비스 구현 분석

궁금했던 점

  • 10분에 한번씩 스케줄링? 그러다 다른사람이 먼저 사가면?
  • 상품 등록시 바로 notify? 유저가 많으면 부하가 너무 생기지 않나?

제안

관련 자료

@hello-yoochul hello-yoochul added Doc Improvements or additions to documentation Analysis labels Apr 16, 2023
@tae0y
Copy link
Contributor

tae0y commented Apr 16, 2023

안드로이드와 애플은 자체 알림 API를 제공
안드로이드는 백그라운드 서비스를 사용해서, 직접 소켓 통신으로 알림을 구현할 수도 있겠음

그러니까 웹API나 소켓통신한다고 가정하고 진행하면 좋을듯

아키텍처는 그림으로 표현해서 공유해주기

@tae0y
Copy link
Contributor

tae0y commented Apr 23, 2023

목표성능

초당 1500 요청을 누락 없이 지원

구현해야할 기능

  • 사용자는 '키워드'를 등록해둔다.
    • UserController > UserService > UserRepository
    • 사용자/키워드중 어떤걸 기준으로 데이터를 저장해야할까?
      • user : keyword를 1 : N 으로 테이블에 저장? keyword : user를 1 : N 으로 테이블에 저장?
      • 가정1) 사용자들이 등록하는 키워드는 정형화되어 있다(이를테면, 실내자전거/닥터마틴)
      • 가정2) 키워드가 정형화 되어 있으므로, 사용자가 등록하는 키워드는 서로 겹칠 것이다
      • 가정3) 사용자별로 키워드를 등록해두면, 특정 키워드에 대해 알림받을 사용자를 모두 검색하는 데 시간이 오래 걸릴 것이다.
      • 따라서 키워드를 기준으로, 해당 키워드에 알림을 보내줄 사용자를 등록해준다 <<
        • 이슈사항) 그런데 어떻게?
          • V 인덱스를 키워드 쪽에 걸어주고 (키워드, 사용자1) (키워드, 사용자2)
          • postgres의 배열 타입을 사용하고 (키워드, 사용자1 사용자2 ...)
          • 직렬화된 데이터를 저장하고 (키워드, {id:사용자1, id:사용자2})
        • 사용자/키워드 저장공간을 절약하고, 알림받을 사용자 검색하는 자원을 절약
        • 예시) 실내자전거 : 박태영, 김유철 / 닥터마틴 : 김유철, 장서윤 / 화분 : 박태영
  • 서버는 '키워드'에 해당되는 '물품'이 등록됐는지 감지한다.
    • 물품이 등록된후, 등록된 물품에 해당되는 키워드가 있는지 확인한다?
    • 일정주기로, 등록된 물품에 해당되는 키워드가 있는지 확인한다?
    • 해당 키워드를 등록한 유저 모두에게 알림을 발송한다
    • observer 패턴?
    • db를 검색?
    • 이슈사항) 캐시? <<
  • 사용자는 등록한 '키워드'에 대한 알림을 받는다.
    • 키워드에 대해서 알림받을 사람을 검색하고
    • 구글/애플 API를 사용해 알림을 발송한다
      • FCM의 경우 기기별로 앱설치할때 사용자한테 토큰을 발급해준다
      • 해당 토큰을 DB에서 사용자별로 매핑해두고, 알림을 발송할때 사용한다
        • 이슈사항) DB레벨에서 세션을 관리하는데, 사용자 많아지면 조회시 부하가 걸리지 않을까?
    • 웹의 경우 웹socket을 사용해 알림을 발송한다
      • 최초에 웹페이지에 접속할때 소켓을 연결해두고 알림 이벤트가 발생하면 해당 소켓으로 브로드캐스팅한다
      • 스프링의 WebSocketSession을 사용해서 사용자별로 소켓세션을 관리할 수 있다
        • 이슈사항) 어플리케이션 레벨에서 세션을 관리하는데, 사용자가 많아지면 부하가 걸리지 않을까?
    • 누락없이 알림을 발송하기 위해서
      • 사용자 요청만 받아내는 요청큐와
      • 실제로 요청을발송할 때 사용하는 발송큐를 분리해서 운영한다
      • img

@tae0y
Copy link
Contributor

tae0y commented Apr 23, 2023

@tae0y
Copy link
Contributor

tae0y commented Apr 27, 2023

당근마켓 알림모듈 다이어그램-순서도 drawio (4)

  • 우리가 구현할 부분: 빨갛게 표시한부분

    • 푸시 - 키워드등록
    • 푸시 - 가격제안
    • 푸시 - 푸시요청/발송
      • 요청큐/발송큐 구조
      • 스케줄실행 : cron으로 웹 요청을 보내는걸로 갈음함
      • 알림수단별로 알림을 발송
  • 그래서 우리가 해야할 일은

    • 테이블/VO확정 < 도커 올려서 ERD 보고 피드백 주기
      • 꼭 필요한 테이블 : 사용자, 물품, 위시리스트, 키워드, 가격제안, 푸시요청/발송
    • 알림API별로 필요한 데이터셋 확인 < API요청보낼때 어떤 데이터가 필요한지까지
      • 구글
      • 애플
    • 요청큐/발송큐 구조에 대해서 다시한번 고민해보자 < 이 구조가 맞을까?
      • 알림수단별로 필요한 정보가 다를텐데 요청/발송큐 스키마를 어떻게 짜야할까?
      • 요청큐와 발송큐를 분리하고, 스케줄로 실행하는게 맞을까?
        • 삽입성능 : 요청큐는 아무 인덱스 없이 삽입성능만 높여서 초당 1500건 이상의 입력을 받을 수 있도록 한다
        • 재시도 : 발송이 실패하더라도, 요청큐에 남아있으므로 다음 스케줄때 재시도할 수 있다
        • 인덱스 없어서 조회성능 떨어지니 요청큐>발송큐로 옮길때, 요청큐에서 삭제할때 지연이 있을것 같다

@tae0y
Copy link
Contributor

tae0y commented Apr 30, 2023

  1. 유철 : 키워드 등록, 위시리스트 등록, 가격 제안
  2. 태영 : 물품 등록/변경 (도커에 db 올리기 계속 진행)
  3. 서윤 : 푸시 요청/발송 내부로직
  • 알림 발송하는 부분은, 카톡 오픈 API / 메일 등으로 목업 (방식은 고민)
  • JPA 어려운 부분은 서로 물어보기
  • 두번째 세션은 테스트코드작성(= 요구사항을 명확하게 목록화)

@tae0y
Copy link
Contributor

tae0y commented Apr 30, 2023

요청큐의 삽입성능

  • 요구사항 : 요청큐는 삽입 성능이 좋아야한다
  • 결론 : 굳이 뭔가를 할 필요 없음
  • 검토한내용
    • 인덱스를 걸지 않기 <- 안해도됨
    • postgres 데이터복구/이중화 logging 끄기 <- 안해도됨
      • 100만건 랜덤 입력시, 로깅켜면 11초 끄면 6초

요청큐에서 발송큐로 데이터 옮기는 방법

  • 요청큐 > 발송큐 데이터 옮길 때
    • 스케줄 실행
      • A프로그램이 > 발송요청 > 요청-발송큐
        • 발송요청 실패시 요청큐에 무한히 남아있음
        • 데이터파기, 재시도로직을 A프로그램에서 진행해야함
      • A프로그램은 요청큐삽입후 잊어버림, 스케줄에서 요청-발송큐
        • expire date, 재시도 횟수 설정 필요할듯

알림API별로 데이터구조가 다를까?

  • 알림API별로 필요한 데이터는?
    • 안드로이드는 FCM(주제구독/기기그룹/기기단독 사용자-사용자토큰 1:N), 애플 APN, 웹 웹푸시API(크롬~사파리)
    • 모바일 : 사용자 기기에서 만든 토큰
    • 웹브라우저 : 보안용 공개키/개인키 암호화 관련 칼럼 2개

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Analysis Doc Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants