Upload
jeongsang-baek
View
1.030
Download
6
Embed Size (px)
Citation preview
Live Operation by AdbrixNode.js와 MongoDB를 이용한 멀티-테넌트 인프라 구축사례
IGAWorks백정상
발표자
• 넥슨• 클래식 RPG (바람의나라 ~ 테일즈위버)
• 엔씨소프트• 스틸독, 마법천자문 온라인, MxM
• 블루윈드• 가로세로 for kakao, LINE QUIZ
• IGAWorks• Adbrix, Live Operation
발표의 목적
목적
• 다수 앱이 사용하는 운영툴을
• 짧은 시간 안에
• 혼자서 다
• 개발해야 할 때 겪은 경험(삽질)과
• 지혜를
• 편한 마음으로 공유
내용
• 거창한 것은 없습니다
• 현실 타협만 가득합니다
• 꿀팁을 드리려 노력했습니다
개발 동기
앱을 출시 하기까지
• 앱 디자인
• 앱 컨텐츠 개발
• 수익화 모델 준비
• 운영 및 관리 툴
• 퍼블리싱 준비
• 런칭
전체 개발 기간을 100으로 놓으면
1 10090
앱디자인및컨텐츠개발 그외작업
개발사가중요하게생각하는것
컨텐츠 개발
컨텐츠 개발이 거의 끝나면
나머지작업들이지연되면
출시 일정 연기
개발사가 진짜 원하는 것
무엇을 도울 수 있을까
무엇을 도울 수 있나
• 클라우드 서버를 제공?
• 네트워크 라이브러리?
• BaaS?
• 게임 컨텐츠 빌더?
• 결론• 컨텐츠 개발은 개발사가 직접 하는 게 맞겠다
• 라이브 운영이라면 도울 수 있겠다
라이브 운영 서비스
• 지금 당장 중요한 고객들에게
• 푸시도 날리고
• 공지도 보여주고
• 리워드도 주고
• 쿠폰도 뿌리고
• 크로스 프로모션도 해주고
• 캠페인 결과를 리포트로 보여주는
• 앱 운영에 필요한 모든 기능을 제공하자
프로젝트 요구사항
요구사항
• 쉽게 사용 가능하도록 무료 서비스
• TCO 최소화
• 하나의 클라우드 인프라에 모든 앱이 서비스 가능하도록
• 하나의 인프라에 장애가 발생해도 서비스에 문제가 없어야 함
• 유저그룹 실시간 타게팅이 가능해야 함
• 실시간 결과 리포트가 되어야 함
• 365일 24시간 서비스
• 혼자서 만들면 얼마나 걸릴 것 같아?
왜 우리에게 주어지는 시간은 늘 3개월인가
테크 스택무엇을 가지고 만들까
프론트-엔드 웹 서비스
• 웹 페이지 서비스는 대규모 인프라가 불필요
• 고민할 것 없이 ASP.net MVC + bootstrap + MSSQL
• 성능과 생산성을 동시에
백-엔드 웹 서비스
• ASP.Net MVC VS node.js
• C#이냐 자바스크립트냐
• 윈도 라이선스냐 생산성이냐
• 빨리 만들어야 한다
• 대부분의 요청이 간단한 CRUD일 것이라 판단
• 손에 익고 오픈소스인 node.js 선택
node.js
• 비동기 I/O 프레임웍
• google V8 + libuv
• 간단한 형태의 대량 비동기 I/O 리퀘스트 처리에 적합
• 활발한 에코 시스템
데이터베이스 요구사항
• 시스템에서 저장하는 정보• 애드브릭스에서 얻는 유저 디바이스에 대한 정보 (1일마다 갱신)
• 개발사가 저장하는 정보• 유저 행동으로부터 실시간으로 얻는 정보 (실시간 갱신)
• 각 개발사마다 저장하는 정보의 형태가 다르다
• 하나의 일반적 스키마로 정의하기 어렵다
• 모든 컬럼이 검색 조건
고려했던 기술
• mariaDB + Redis?• 앱별로 다른 스키마를 어떻게 일반화 할 것인가
• MongoDB• 2.6 기준으로 insert 퍼포먼스가 별로
• 스키마 없음
• node.js와 궁합이 좋음 (같은 자바스크립트 기반)
• 다양한 인덱싱
• Couchbase• 준수한 성능, 꽤 괜찮은 리플리케이션
• 아쉬운 인덱싱
MongoDB
• BSON 도큐먼트 저장소
• 다양한 인덱싱 방법 지원
• 메모리-맵드 파일 기반
• 준수한 읽기 성능
• 스키마 없음
• Mongoose.js를 쓰면 node.js로 빠르게 구현 가능 하겠구나
킥오프!
개발 환경 정리
• 프론트-엔드 : ASP.net MVC + bootstrap
• 백-엔드 : Node.js 0.10.x
• 데이터베이스 : MongoDB 2.6.x
• ODM : Mongoose.js
• BDD : Mocha
• IDE : VS2012, Webstorm
• OS : Ubuntu 14.04 LTS
• SDK : iOS / Android
• Deployment : AWS (Tokyo)
빠른 프로토타이핑
• 모든 백엔드 API 구현에 1주일정도 소요
• 웹 프론트엔드 작업 2주
• 프로토타입이 2주만에 나옴
• 만족스러운 생산성
초기 시스템 구성
애드브릭스웹사이트
백엔드 API
몽고DB(단일인스턴스)
모바일디바이스(SDK 연동)
캠페인 API(푸시서비스)
액티비티트래킹
디바이스액티비티트래킹그룹
고민
• DB 퍼포먼스 == 서비스 퍼포먼스
• 데이터베이스 리소스를 어떻게 앱마다 쪼개서 제공할까
• 안정성은 어떻게 유지해야 할까
• 성능 최적화는 어떻게?
• 모니터링은 무엇으로?
• 멀티-테넌트 인프라?
멀티-테넌트 인프라
멀티 테넌시의 4대 요소
• 안전한 분리• 사용자 데이터는 격리되어야 함
• 서비스 외부에서 타 앱 리소스에 접근 불가능
• 가용성• 리소스 하나에 문제가 생겨도 전체 서비스에 문제가 발생하지 않아야 함
• 서비스 보장• 일정 수준의 SLA 보장
• 관리• 전체 시스템 모니터링이 가능해야 함
데이터 격리
• 제일 고민이 컸던 부분
• 구글링 해보니 굉장히 다양한 방법이 있었음
• 1 앱 == 1 EC2 인스턴스?
• 1 앱 == 1 docker container?
• 1 앱 == 1 database?
• 1 앱 == 1 collection?
1앱 == 1 EC2 인스턴스
1앱 == 1 docker container
• 장점• 확실한 형태의 분리
• 분리 대비 리소스 효율적
• 단점• 앱이 10000개가 된다면? 10000개의 이미지를 관리?
• dbpath로 데이터를 관리 하자니 관리 코스트가 크다
• 이미지가 커져서 서비스 중 이전해야 한다면?
• 결국 관리 시스템을 만들어야 하는 상황
1앱 == 1 database
• 장점• 2.6 기준으로 데이터베이스별 쓰기락 지원으로 병렬성 확보
• 컬렉션 관리가 용이
• Mongoose 연동이 간편
• 단점• 기본 생성되는 데이터파일 사이즈가 64MB(데이터) + 16MB(네임스페이스)
• 앱 5000개면 도큐먼트가 0개여도 400GB
• 비효율적인 스토리지 사용
• Provisioned IOPS EBS는 매우 비쌈
1 앱 == 1 collection
• 장점• 비용 효율적
• 단점• 2.6 기준 병렬성 이슈 발생
• 앱과 컬렉션간의 매핑이슈와 uniqueness문제
• 네임스페이스 이슈
• 1앱이 여러 컬렉션을 써야 한다면?
• Mongoose에서 지원하지 않음
1앱 == 1 컬렉션을 선택
• 제일 비용 효율적
• 차기 버전에서 document-level locking이 지원될 것이란 소문• 3.0에서 wiredtiger가 도입되면서 그것이 실제로 일어났습니다!
• 애드브릭스 앱키 + 컬렉션 이름으로 uniqueness를 설정
• 컬렉션 이름을 해싱하여 저장하고 mapper를 구현
• CBT을 해보니 Write보다는 Read 위주인 사용 패턴
• 페이지 폴트만 조심하면 성능 하락 요인이 적다
개념적으로
애드브릭스웹사이트
백엔드 API 몽고DBappKey:103932name:users
db.[‘103932_users’].find()
리소스 접근 제어
• 공용 REST API 미지원
• 로그인 외 모든 리소스 요청에는 인증 세션을 요구
• 각 컬렉션에 접근권한 부여
• MongoDB를 격리된 VPC 내에 배치하고 WAS만 접근 가능하게 설정
가용성
• WAS• 는 무조건 stateless
• ELB와 오토-스케일 그룹을 통해 구성
• DB• 리플리카 셋을 구성
• 제일 비용 효율적인 구성을 하자
• 2개의 리플리카 셋 멤버를 2대의 r3.2xlarge에
• 1개의 아비터
• 1TB의 provisioned IOPS EBS * 2
서비스 보장
• AWS님만 믿고 가자
• 다행히 서비스동안 mongodb 리플리카 멤버 1번 사망한 것 빼고 리소스에 문제 생긴 적이 없음
• EBS의 경우 기본 데이터 3중화
• ELB에 등록할 경우 알아서 availability zone을 균등하게 분배
관리
• 직접 (급하게) 만든 Control tower• Github -> docker image -> auto-scale group 자동화
• MongoDB Management Service 도입
• Amazon CloudWatch
꿀팁 모음
디비가 꽉차면 어쩌지?
• 130여개 앱이 사용하자 벌써 100GB+
• 디스크 용량 제한에 걸리면 어떡하지?
샤딩
• 몽고디비 샤딩은 컬렉션 단위
• 오토 리밸런스 작동시 리소스 관리가 어려움
• 앱 추가될 때 마다 컬렉션 생성하고 수작업으로 샤딩 걸고..;;;
• 현실적으로 손이 많이 가서 제외
수동 페더레이션
• 온라인 게임 서버 증설하는 방식
• 기존 리플리카 셋의 페더레이션 아이디는 0
• 새로운 페더레이션 멤버가 추가될 때 마다 페더레이션 아이디 증가
• 이후 등록되는 앱 정보는 다음 페더레이션 멤버에 추가하도록
• 페더레이션 멤버 추가시 수작업이 필요
• 페더레이션 맵퍼 수작업 구현
최적화
• 크게 두 가지만 기억하세요
• Locking 이슈
• Indexing 이슈
Lock 관리
• 일괄입력, 일괄 업데이트 금지• 모든 쓰기 행동은 비동기로 짧게 진행되도록 처리
• 일괄처리의 휴리스틱 최대치는 1000개
• MapReduce나 Aggregate 금지• 서비스에 영향을 미칠 정도의 과부하 발생
• 바보같은 스토리지 형태로 쓰세요
• 복잡한 계산은 스케일 아웃 가능한 WAS에서 하도록
• 가급적이면 read는 secondary preferred로
• CEP의 경우 Capped Collection을 쓰면 write성능 대폭 상승
Index 관리
• 컬렉션당 최대 인덱스 개수는 64개
• 인덱스 대상의 최대 사이즈는 1KB
• 네임스페이스를 최대한 키울 것. 1GB 정도까지
• explain()의 생활화
• 인덱스 생성을 가급적 적게 하고• 한번에 많이 할 경우엔 foreground로
• 빈번하게 해야 할 경우엔 background로 설정
• 인덱스가 많으면 당연히 write 퍼포먼스 하락
• Projection을 통해 Covered Query를 최대한 활용하세요
멀티-테넌트 컬렉션 관리자
• 스키마가 없어서 좋긴 한데
• 앱마다 저장되는 정보가 다르고
• 인덱스도 다 다르고
• 권한도 다르고
• 어떤 컬럼이 커스텀 유저 액티비티인지
• 어떤 컬럼이 시스템 필수인지 누군가는 알아야 함
• 결국 다 관리해주는 컬렉션 관리자를 구현해야 했습니다 orz
Mongoose.js 관련
• 패스트 프로토타이핑땐 좋았음
• 멀티-테넌트 인프라에선 비추천
• 기본적으로 1개의 독립적인 디비를 사용하는 형태를 기준으로 개발됨
• Native driver로 구현하시는 것이 정신 건강에 좋습니다
실시간 유저 타게팅
• 유저 그룹 조건을 저장해뒀다가
• 매번 필요할 때마다 쿼리
• MongoDB 검색은 진짜 빠름
• 메모리 사이즈가 클 수록 성능 배가
• 효율적인 인덱싱이 최대 과제
맺음말
현재 간략 구성도
애드브릭스웹사이트
백엔드 API
모바일디바이스(SDK 연동)
캠페인 API(푸시서비스)
액티비티트래킹
디바이스액티비티트래킹그룹
푸시센더그룹
푸시이벤트스토어
MongoDB RS Federation 0
페더레이션관리자
사용량
• 130+ 업체에서 무료로 사용 중
• 16,000,000+ 일 최대 유저 커스텀 액티비티 트래킹
• 300,000,000+ 누적 푸시 메시지 발송
후기
• 빠르게 시작해서 돌아가는 그림을 보고
• 비즈니스와 기술적 요구사항 존중하니
• 엄청나게 많은 부분을 수정하고 다시 만들었습니다
• 근데 딱 6개월 걸렸습니다
• 정확히 예상 일정의 2배 걸렸네요
• Node.js + MongoDB 조합 쓸만합니다
감사합니다