티스토리 뷰

https://youtu.be/BnS6343GTkY

들으면서 요약하였음

2015년. 처음에는 모놀리틱 서비스 였다. 리뷰 시스템쪽에 장애가 나더라도 시스템 전체가 먹통되는 일이 생기곤 했다. 하루 주문수 10만건이 넘어가면서 마이크로서비스 도전을 시작했다.

참고로 루비는 레거시 DB의 총칭

주문수 증가 수치가 놀랍다.

처음에는 결제 서비스를 따로 떼어냈다.

결제 서비스 죽으면 끝나는게 아닌가? 아니다. 전화 주문도 가능하다. 따라서 시스템 전체가 멈추는 일은 없어야 한다.

주문중계 : 치킨 주문시 사장님들이 앱, 단말기, PC 등으로 주문 받을 수 있음. 이걸 중간에서 포워딩 해주는 서비스였음. Node JS로 구현했었지만 규모가 커지면서 JAVA로 다 바꿨다.

오후 5시 선착순 7천명에게 치킨 싸게 주는 이벤트때 트래픽이 몰림

IDC to AWS 이전은 원래 한달 플랜이었지만, 연일 이어지는 이벤트에 대응하기 위해 밤을 새서 하루만에 끝냈음.

하지만 프론트를 다 마무리 했어도 주문 서버가 죽음. 이것도 또 AWS로 옮김

문제는 이를 받아주는 PG사 서버가 뻗었음. 이건 PG사에서 서버를 급하게 수급해서 장비 2대를 늘려서 처리 완료.

이렇게 4일에 걸쳐서 성공 시킴

오후 5시만 되면 서버가 뻗었음.

가게 목록, 검색을 엘라스틱 서치로 떼어냈음

회사 1순위 과제가 시스템 안전성이 되었음.

가게 상세 서비스를 루비DB에서 AWS Dynamo DB로 옮김

2018년 상반기에 분리된 마이크로서비스는 위와 같음

하반기엔 주문을 분리함. 주문이 모든 커머스 시스템에서 제일 복잡하다. 주문 하고 나면 다른 모든 서비스랑 소통해야 한다.

 

가장 거대한 레거시인 주문, 가게/업주, 광고를 어떻게 분리 해야할까?

우선 주문 부터 살펴보면, 배민 주문과 배민 라이더스 주문을 따로 처리 하고 있었는데 사실 기능이 거의 유사했음

시스템을 통합하고 어플리케이션으로 분기하도록 약간 수정함

태초 주문 시스템은 API 기반이었음. 하지만 리뷰 시스템에 장애가 나면 주문 시스템도 이를 처리 하지 못하고 장애가 났음.

이제 주문 시스템은 이벤트 기반으로 바꿈. 주문 시스템은 이벤트를 발행만 하고, 각 시스템에서 이를 구독하고 가져가서 처리 한다.

이 시스템의 장점은, 리뷰 시스템이 죽었어도, 죽었다 살아나면서 SQS에 쌓여있는 이벤트를 Consume 할 수 있다는 점이다.

또 이것의 장점은, 다른 새로운 서비스가 '우리 주문 시스템이랑 뭐 하고 싶어요~'라고 하면, 주문 시스템은 할 일이 아무것도 없다. 새로 만든 서비스가 스스로 주문 서비스의 SQS를 구독하면 끝이다.

이제 남은 두개를 어떻게 옮기느냐가 관건. 이 둘을 옮기려면 거의 비지니스가 멈춰야 한다.

약 4개월이 필요하다.

AS-IS. 가게 상세, 가게 목록 + 검색 등등이 루비의 가게 데이터, 광고 데이터를 바라보고 있다. 이걸 어떻게 떼어낼 것인가? 특히 가게 데이터와 광고 데이터가 엄청 섞여 있다.

위와 같이 구성하기로 함

광고 시스템이 죽으면? 연관된 서비스가 다 죽는다.

대용량 트래픽이 확 하고 들어올 때가 있다. 그러면 이 트래픽이 모든 서비스로 퍼진다.

위 조건을 어떻게 준수 할 것인가?

가게나 광고 같은 서비스에는 장애가 생긴다 하더라도, 주문까지는 무조건 가능해야 한다.

추가적으로 분리된 데이터들을 어떻게 동기화 할 것인가에 대한 문제도 있었음.

그렇게 해서 최종 결정한 것이 CQRS 시스템.

예를 들어 사장님(가게/업주)에서 업체명/전화번호를 바꾼다고 하면, 이걸 아래와 같이 이벤트로 쏜다.

그러면 필요한 서비스들이 알아서 그걸 Consume 한다.

최종적 일관성 : 언젠가는 다 싱크가 맞춰진다.

문제 발생시 이벤트를 재 발생 하는 식으로 해결

Zero-payload란?

이벤트 발행시 메세지를 다 담아서 보내는게 아니라 딱 가게ID만 보낸다.

수신한 곳에서는 가게ID를 이용해서 API를 호출한다.

이렇게 한 이유는

  1. 이벤트 순서를 고민할 필요가 없다. 가게 연락처를 A로 바꿨다가 B로 바꿨다고 해보자. 근데 무조건 이 순서로 오지 않는다. B가 먼저 올 수도 있다. 이게 페이로드로 담겨서 오면 순서가 바뀔경우 문제가 있을 수 있지만, Zero-payload 사용시 어짜피 최종 데이터를 가게/업주 서비스가 갖고 있기 때문에 문제가 되지 않는다.
  2. 각 시스템마다 원하는 데이터가 다르다. 따라서 모든 데이터를 다 담아서 보내기엔 현실적으로 한계가 있다.

필요 없는 정보는 갖지 말고 최소한의 정보만 갖자

성능이 중요하면 레디스, DDB 쓰고, 검색 같은 곳은 엘라스틱 서치 쓰고.. 시스템에 맞는 것을 씀

DB는 위와 같이 쓰고 있음

가게 노출 같은건 불러줘야 할게 많다. 이를 동기화 해주는 유저 서비스용 가게 데이터를 따로 관리 해준다.

가게 ID만 넣으면, 렌더링에 필요한 데이터만 퀵하게 바로 뿌려줄 수 있도록 데이터를 플랫하게 만들어 놓는다.(키-밸류 스토어 인듯)

예를 들어 가게 검색 결과가 25개 나왔다고 해보자 (아마도 이건 엘라스틱서치를 통해 검색한 결과일듯?)

그러면 가게 아이디만 25개를 들고 있게 된다. 그다음 25개 아이디를 갖고 25번 찔러 본다. 키-밸류 형태기 때문에 값이 금방 나온다. 앱에서 렌더링 할 수 있게 데이터를 씌우고 리턴한다.

가게 상세 부분은 비동기 Nonblocking으로 돼있다.

CQRS 아키텍쳐 도입 후, 뒷단은 아예 보지 않게 되었다.

쿼리가 들어오면 '조회용' 시스템만 트래픽을 받게 된다.

가끔 SQS, SNS 장애가 날 때가 있다. 잘 없긴 한데 일년에 종종 몇번 장애가 난다. 위와 같은 형태로 장애를 대응한다. API가 있기 때문에 이걸 쓰면 된다.

비동기 부분은 주로 WebFlux로 돼있다.

2019년 11월 1일 완료!

마지막

MSA를 꼭 해야 하나요?

규모의 경제가 필수다. 그냥 Join 한번 하면 되는걸 MSA에서는 데이터 싱크 하고 맞추고 하다보면 비용이 10배도 더 들 수도 있다. 이걸 상쇄하고도 남을 만큼의 가치가 있을 때 MSA로 넘어가는게 좋다.

TAG
, ,
댓글
댓글쓰기 폼