본문 바로가기
정보공유

[정보] 신입사원을 위한 웹서비스 확장 전략

by 날고싶은커피향 2018. 3. 6.

신입사원을 위한 웹서비스 확장 전략 관련 자료입니다.

내용 참고 하시기 바랍니다.

 

 

webservice scaling for newbie from DaeMyung Kang

 

1. 신입사원을 위한 웹서비스 확장 전략 강대명 (CHARSYAM@NAVER.COM)
 2.  본인 소개 현) 유데미 데이터 엔지니어 구) 카카오 스토리 백엔드 엔지니어 구) 네이버 메일 백엔드 엔지니어 여러 오픈 소스에 컨트리뷰션 중입니다.
3.  주제 웹서비스를 확장하기 위해서 알아야 할 방법들
4.  쉬운 방법 서버를 빵빵하게 넣어둡시다. 다만 버는 것보다 쓰는 게 많으면…
5.  대규모 서비스 개발 노하우의 필요성
6.  2011년 bit.ly 하루에 1억 5백만 클릭 (실제 사람이 한 것만) 대략 초당: 1216 clicks 현재는?
7.  2010년-2011년 Netflix API 1년 사이에 트래픽 20배 증가 20B = 20,000,000,000
 8.  2017년 배틀그라운드 6월7일에 대략 20만 9월5일에는 100만
9.  우리는 이런 서비스 트래픽 증가를 버틸 수 있을까?
10.  첫번째 고려 사항 1. 이 정도의 서비스 증가가 일어나면 어떻게 해야할까? 2. 한동안 서비스가 안된다면 어떤 일이 벌어질까?
11.  대규모 서비스의 특성
12.  Elastic Resiliency
 13.  대규모 서비스의 특성  Elastic 트래픽이나 상황에 따라서 서버의 추가/제거가 쉬워야 한다.  Resiliency 특정 장비의 장애 등은 자동으로 복구가 되어야 한다. 서버가 복구되는 건 아님 해당 장비의 장애로 인해 다른 쪽이 영향 받지 않아야 함
14.  Scale Up VS Scale Out
 15.  Scale Up
 16.  초당 1000 TPS
 17.  초당 3000 TPS 3배 처리 가능한 서버를 투입
18.  Scale Out
 19.  초당 1000 TPS
 20.  초당 2000 TPS
 21.  초당 3000 TPS
 22.  SPOF Single Point Of Failure
 23.  여기에 장애가 나면 서비스 전체를 마비시키는 병목지점
24.  SPOF API Server DB Server 한대의 물리 서버
25.  SPOF API Server DB Server 한대의 물리 서버
26.  SPOF API Server DB ServerClientClientClient
 27.  SPOF API Server DB ServerClientClientClient
 28.  SPOF API Server DB ServerClientClientClient
 29.  SPOF ClientClientClient API Server API Server DB
 30.  SPOF ClientClientClient API Server Master DB Slave DB Replication
 31.  SPOF ClientClientClient API Server API Server API Server Master DB Slave DB Replication
 32.  Name Service - DNS ClientClientClient API Server API Server API Server Master DB Slave DB
 33.  DNS Query Result Domain IP www.naver.com 125.209.222.142 202.179.177.21 www.google.com 203.233.96.58 203.233.96.57 203.233.96.56
 34.  Name Service - LB ClientClientClient API Server API Server API Server L B Master DB Slave DB
 35.  어디를 확장해야 할까?
36.  API 서버? DB 서버?
37.  API 서버  API 서버에만 부하가 몰리는 작업은 어떤 것이 있을까? 파일 IO가 많은, 정적 파일 서빙 웹 스크래핑과 같은 디비 작업 자체보다는 다른 작업이 많은 녀석들 독립적인 작업이 가능한데, CPU나 다른 작업이 많이 필요한 LOL, 배그같은 MO 게임서버 이미지의 영상 인식이나 전처리 이런것도…
38.  DB 서버  카톡방의 대화는?  페이스북의 글, 댓글, 친구 관계?  유투브 등에 올라가는 비디오나 댓글등  생각보다 우리가 아는 대부분이 여기에 부하를 줌.
39.  Stateless
 40.  State
 41.  State Client API #1 User #1 API #2 User #2 User #3 User #4
 42.  State Client API #1 User #1 API #2 User #2 User #3 User #4 1. 5번 유저 추가되면 어디로 가야할까?
43.  State Client API #1 User #1 API #2 User #2 User #3 User #4 1. 장애가 났을 때 User #3, #4의 데이터는 어디로?
44.  Stateless Client API Storage API API API 서버는 비즈니스 로직만 가짐
45.  조삼모사? Client API StorageAPI API 크고 안정적인 디비가 필요하게 됨.
46.  Stateless 한 서버의 경우  장점 추가/삭제가 간단함. 사용하는 쪽에서 주소만 추가하거나 제거하는 걸로 가능 Or 로드밸런서에 추가하거나 제거 하기만 하면 OK  단점 결국 데이터의 저장이 필요하므로, 뒤에 책임을 떠 넘기는 구조임. 개별 성능은 Stateful 한 경우보다 떨어질 수 있음
47.  그런데 왜 Stateless 인가?  Stateless 한 서버에 신경을 쓰지말고  중요한 DB(Storage) 쪽에 집중을 하는게 더 좋다라는 판단.  두 마리 토끼를 다 쫓지 말고, 한 놈만 팬다.
48.  Shard Nothing
 49.  API 서버는 Stateless 그럼 DB는!!!
50.  일반적인 DB 서버의 부하 200 writes/s 800 reads/s Read > Write
 51.  읽기 분배 - Query Off WEB/AS Master Slave ONLY WRITE Slave Slave Only READ REPLICATION
 52.  읽기 분배 - Query Off 200 writes/s 800 reads/s 200 writes/s 400 reads/s 200 writes/s 400 reads/s Read/1 Server Read/2 Server
 53.  Slave 장비를 추가하면 계속 성능이 증가할까?
54.  읽기 분산의 한계 700 writes/s 50 reads/s 700 writes/s 50 reads/s 700 writes/s 50 reads/s 700 writes/s 50 reads/s 700 writes/s 50 reads/s Write Heavy Situation
 55.  Database Partitioning
 56.  Vertical Partitioning
 57.  Horizontal Partitioning
 58.  Sharding Horizontal Partitioning
 59.  특정 Key 를 어디에 저장할 것인가?
60.  특정 Key 를 저장하는 방법 특정 Key 를 찾는 방법
61.  질문: 어떻게 데이터를 나눠야 할까?  가정 #1 하나의 서버에는 최대 5개의 데이터만 저장 1, 2, 3, 4, 5, 6 의 데이터가 있을때, 어떻게 데이터를 나눠야 데이터를 잘 저장했다고 할 수 있을까?
62.  질문: 어떻게 데이터를 나눠야 할까?  가정 #2 7,8 의 데이터가 더 들어왔을때는?
63.  Range 특정 범위대역으로 나누기 Server #1 Server #2 Server #3 User #1 ~ 100 User #101 ~ 200 User #201 ~ 300
 64.  Modular 서버 대수로 나누기 Server #1 Server #2 0 % 2 = 0 1 % 2 = 1 2 % 2 = 0 3 % 2 = 1 4 % 2 = 0 5 % 2 = 1
 65.  Modular Modular의 단점 한대가 추가되면? 데이터의 이동이 심해진다. Server #1 Server #2 0 % 3 = 0 1 % 3 = 1 Server #3 2 % 3 = 2 3 % 3 = 0 4 % 3 = 1 5 % 3 = 2 6 % 3 = 0 7 % 3 = 1 8 % 3 = 2
 66.  Modular 두배로 늘리기 1에서는 3으로 절반이, 2에서는 4로 절반이 이동 Server #1 Server #2 0 % 4 = 0 1 % 4 = 1 Server #3 Server #4 2 % 4 = 2 3 % 4 = 3 4 % 4 = 0 5 % 4 = 1 6 % 4 = 2 7 % 4 = 3 8 % 4 = 0 9 % 4 = 1 10 % 4 = 2 1 % 4 = 3
 67.  Indexed 특정 데이터의 위치를 가리키는 서버가 존재 Server #1 Server #2 Server #3 User #1 Index User #1 -> 3 User #100 -> 1 User #102 -> 1 User #100 User #102
 68.  Complexed Master Index User RANGE #1 -> 1 Slave Slave Master Slave Slave Master Slave Slave ONLY WRITE ONLY READ User RANGE #10 -> 1 User RANGE #20 -> 3
 69.  Consistent Hashing
 70.  A Add A,B,C Server
 71.  A B Add A,B,C Server
 72.  A B C Add A,B,C Server
 73.  A B C 1 Add Item 1
 74.  A B C 1 2 Add Item 2
 75.  A B C 1 2 3 4 5 Add Item 3,4,5
 76.  A B C 2 3 4 5 Fail!! B Server
 77.  A B C 1 2 3 4 5 Add Item 1 Again -> Allocated C Server
 78.  A B C 1 2 3 4 5 1 Recover B Server -> Add Item 1
 79.  C가 죽으면 A 부하가 너무 커지지 않을까요?
80.  A B C 1 2 3 4 5 1 예상도
81.  그러나 실제로는?
82.  A B C Real Implementation A+1 A+2 A+3 B+1 B+2 C+1 C+2 A+ 4 C+3 B+3
 83.  Consistent Hashing 의 구현 #1 Hash(key) value Hash(server_1) 100 Hash(server_2) 200 Hash(server_3) 300 동일한 Hash 함수를 사용한다면, 같은 KEY에 대해서 Value가 바뀌는 경우가 있을까?
84.  Consistent Hashing 의 구현 #2 Hash(key) value Server Hash(Key_1) 50 Server_1 Hash(server_1) 100 Hash(Key_2) 150 Server_2 Hash(server_2) 200 Hash(Key_3) 230 Server_3 Hash(Key_4) 270 Server_3 Hash(server_3) 300 Hash(Key_5) 350 Server_1 해쉬 값이 자기보다 큰거나 같은 서버들 중에서 가장 가까운 서버로 KEY가 할당됨
85.  메일서비스를 한 번 설계해봅시다.  사용자가 가입하는 경우  사용자가 메일을 수신하는 경우  사용자가 메일 리스트를 보는 경우  사용자가 메일의 상세 내용을 보는 경우
86.  전체 가정  사용자의 메일 정보는 다음과 같이 각각 분리되어 있다. 사용자의 메일 수신 리스트 각 메일의 실제 파일 내용  한 계정의 메일 목록 정보는 모두 같은 DB 안에 존재한다. 즉 한 계정의 정보는 분산되지 않는다.  EML을 저장하는 부분은 AWS S3 같은 서비스를 이용한다고 가정합니다. 여기서 설계나 구조를 현재는 다루지 않습니다.
87.  사용자가 가입하는 경우 #1  어떤 방식을 고려할 것인가? Range Modular Indexed
 88.  사용자가 가입하는 경우 #2  한국의 사용자는 많아도 5천만명, 계정을 3~4개씩 만든다고 하더라도  2억개 정도  메모리가 충분한 DB한대로 충분히 커버가 되는 수준  계산 방법 이메일 주소 : 256 bytes 그 외 추가 정보로 1개당 1024 bytes 라고 가정 1024 * 2억 = 190기가 정도면 모두 메모리에 저장됨.(디스크에 갈 일도 없음.) 8:2 법칙에 의해서 20% 정도가 빈번하게 액세스 된다고 하면 190 * 0.2 = 38G 64G 정도 메모리 머신이면 aws m4.4xlarge 정도 시간당 $1, 한달에 $720 정도 듬. 장애 대비하면 720 * 2 = $1440 정도로 구성 가능(Index 서버만) 실제로 1k 도 안될 가능성이 크므로 더 작게도 구성이 가능함.
89.  사용자가 가입하는 경우 #3  사용자의 메일서비스에 가입할 때, 사용자의 메일 리스트를 저장 할 서버는 현재 서비스 중인 서버들 중에서 가장 사용량이 적은 서 버로 선택 사용량이 적은 서버 디스크 사용량, CPU 사용량이 적은 서버 가장 할당된 사용자가 적은 서버) 서버 평균 사용량(100이 한계라고 가정) A 100 B 90 C 70 D 20
 90.  사용자가 가입하는 경우 #4  User Table Schema 컬럼명 추상타입 비고 user_id Long(64bit) 유니크 고유 아이디(각 DB별) email String 이메일 주소 shard Long 자신의 메일 리스트를 저장한 서버 번호 type int 활성화 유저인지, 아니면 다른 특징정보 created_at timestamp 계정 생성시간 last_login_time timestamp 최종적으로 로그인한 시간
91.  사용자가 메일을 수신하는 경우 #1  가정 수신받는 메일 도메인은 하나로 가정한다.(사실 여러 개라도 상관은 없다.) 메일 내용(EML)은 DB가 아닌 다른 곳에 저장된다. AWS의 S3 같은 것을 생각하자. 메일을 가져가는 방법은, 일단 수신 받은 시간 순으로만 된다고 가정한다. 송신자 순, 메일 제목 순, 이런 건 고려하지 않는다.
92.  사용자가 메일을 수신하는 경우 #2  Mails Table Schema 컬럼명 추상타입 비고 mail_id Long(64bit) 유니크 고유 아이디(각 DB별) receiver String or Long 수신자 sender String or Long 송신자 subject String 메일 제목 received_at timestamp 수신 시간 eml_id String or Long 메일 본문 저장 id(or url) is_read boolean 읽었는지 여부 contents String 보여줄 내용의 일부?(중요하지 않음)
93.  사용자가 메일을 수신하는 경우 #3 송신자 메일 서버 수신자 메일 서버 메일 전송 메일 수신 User Service 정상 유저 확인 메일 파싱 메일 메타 정보 저장 DB #1 DB #2 DB #3 Eml Storage Eml Storage Eml Storage eml Storage 메일 본문 정보 저장 이해를 돕기 위한 아주 추상적인 구조입니다.
94.  사용자가 메일을 수신하는 경우 #4  EML 저장을 위한 서비스가 추가로 필요.  AWS S3 같은 것을 이용한다고 하더라도  결국 해당 EML 파일에 대한 key를 무엇을 할 것인지가 중요함.  EX)  Unique 한 값을 만들어낼 수 있어야 한다. {receiver_id}_{mail_id} Mail_id 자체로는 나눠진 shard 마다 중복이 존재 가능함. {receiver_id}_{mail_id}는 Unique
 95.  사용자가 메일 리스트를 보는 경우 사용자 Mail Service 목록 요청 목록 전송 User Service 정상 유저 확인 메일 리스트 요청 select * from mails where receiver=charsyam order by created_at desc DB #1 DB #2 DB #3 이해를 돕기 위한 아주 추상적인 구조입니다. charsyam: 3 charsyam 메일 리스트 전달
96.  사용자가 메일의 상세 내용을 보는 경우 사용자 Mail Service 이해를 돕기 위한 아주 추상적인 구조입니다. charsyam_1 메일 요청 eml_id 전달 메일 상세 전달 Eml Storage Eml Storage Eml Storage eml Storage
 97.  메일 EML을 저장하는 KEY  EML ID를 왜 {receiver}_{mail_id} 로 했을까? KEY를 만드는 방법은 굉장히 다양할 수 있음.  좀 더 좋은 KEY를 만들 수 있을까?
98.  질문  EML ID 필드가 필요할까요? 이미 receiver 와 mail_id가 있으므로 그냥 조합하면 되지 않을까?  데이터를 다른 서버로 이전해야 하는 경우?
99.  다시 돌아와서!!!
100.  KEY 설계를 어떻게 할 것인가?
101.  키만 보고 어떤 서버에서 찾아야 할지 알 수 있지 않을까?
102.  Unique 해야함
103.  Key만 보고 시간 순을 알 수 있을까?
104.  UUID  Universally Unique Identifier  128 bit  36 characters  123e4567-e89b-12d3-a456-426655440000
 105.  UUID의 단점  128 bit는 너무 용량이 크다.
106.  보통 Shard ID 가 들어감
107.  Shard ID와 실제 서버의 매핑
108.  시간 정보가 들어가면 ID 만으로 시간 정렬이 가능
109.  뭔가 변화하지 않을 특별 한 정보가 있다면 ID에 들어가 있으면 좋음.
110.  오픈 채팅 단톡방 그룹채팅방 비밀채팅방
111.  필요 정보들  시간정보(Timestamp) Timestamp 는 1970년 1/1일 기준, 우리는 2018년 부터 시작해도… 언제까지의 시간 정보가 필요할까? 4byte를 다 쓰면 2106년 2/7일 06:28분 까지 커버됨(32bit)  채팅방 정보  Shard 정보
112.  {TIMESTAMP}_{SHARD_ID}_{TYPE}_{SEQUENCE}
 113.  KEY의 설계 #1  Simple 버전 64bit = 8 bytes 기존 userid 를 생성되는 key 와 붙여서 사용하는 방법 6209324585984 Timestamp = 6209324585984 >> 12 = 1515948385 Sequence = 6209324585984 & 0xFFF = 1024 charsyam_ 6209324585984 Timestamp sequence 52 bits 12 bits = 4096
 114.  KEY의 설계 #2 Client Service KEY 전송 User Service 정상 유저 확인 KEY 파싱 DB #1 DB #2 DB #3 이해를 돕기 위한 아주 추상적인 구조입니다. charsyam_6209324585984 charsyam Shard : 3 KEY 6209324585984 요청 각 유저의 데이터는 각 유저가 지정된 Shard 이외에는 저장될 수 없다.
115.  데이터는 서로 다른 서버 로 나눠질 수 있다면?
116.  KEY의 설계 #3  약간 복잡해진 버전 64bit = 8 bytes 6209324585984 Timestamp = 6209324585984 >> 20 = 1515948385 Shard Id = (6209324585984 & 0xFFF000) >> 12 = 2048 Sequence = 6209324585984 & 0xFFF = 1024 Timestamp Shard ID sequence 40 bits 12 bits = 4096 12 bits = 4096
 117.  KEY의 설계 #4 Client Service KEY 전송 KEY 파싱 DB #1 DB #2 DB #3 이해를 돕기 위한 아주 추상적인 구조입니다. 6209324585984 KEY 6209324585984 요청 6209324585984 = Shard ID 2048 Shard Server ……. …… …… DB #1 2048 DB #2 …… DB #3 …… …… Check Shard Map
 118.  IDC 가 다르다면?
119.  Twitter의 ID
 120.  Instagram 의 ID
 121.  MongoDB 의 ID
 122.  Service Discovery
 123.  Client Side VS Server Side
 124.  Client Side ClientClient예약 Server 결제 Server 결제 Server 결제 Server 예약 서버가 결제 서버를 호출한다고 하면? 1 2 3
 125.  Server Side ClientClient예약 Server 결제 Server 결제 Server 결제 Server 예약 서버가 결제 서버를 호출한다고 하면? Proxy LB
 126.  서버들의 목록은 어디서 가져올까?
127.  서버의 추가 서버의 삭제(장애)
128.  질문  어떤 서비스가 정상인지 알아보는 HealthChecker를 만든다고 가정합니다.  http://api.bob.com/health 를 호출해서 체크한다고 하면, HealthChecker가 정상이라는 건 어떻게 보장할 수 있을까요?
129.  간단한 방법? HealthChecker를 체크하는 HealthChecker를 두자? 언제까지? API 서버 Health Checker #1 Health Checker #2 …… Health Checker #N
 130.  질문 ClientClient예약 Server 결제 Server 결제 Server 결제 Server 결제 서버가 추가/삭제 될때 LB를 쓸 수 없다면 어떻게 해야 할까? 결제 Server
 131.  Coordinator Zookeeper Etcd Consul Eureka
 132.  Zookeeper Data Model 그냥 디렉토리
133.  Zookeeper 의 특징  절대로 죽지않는다.(거짓말) 잘 안죽는다.(몇대 죽어도 상관은 없다.) 그러나 다 죽을때도 종종 있음.  임시 노드의 경우, Health Check를 통해서 자동적으로 접속된 노 드가 사라지면 데이터가 사라진다.(30초가 기본…) Cluster Membership  노드의 순서를 보장해준다. Leader Election
 134.  Leader Election Cluster Membership
 135.  Zookeeper Ephemeral Node
 136.  서버와의 연결이 끊어지면 노드 정보도 사라짐
137.  질문 #1을 다시 살펴보자 : HealthCheck 그냥 API 서버를 체크하는 HealthCheck를 여러 대 두자. API 서버 Health Checker #1 Health Checker #2 Health Checker #3
 138.  질문 #1을 다시 살펴보자 : HealthCheck 장애가 나면 장애 알람이 몇 개나 가게 될까? API 서버 Health Checker #1 Health Checker #2 Health Checker #3
 139.  여러 대 가 있지만, 한 대만 동작하면 좋겠어…
140.  질문 #1을 다시 살펴보자 : HealthCheck Leader 만 동작 API 서버 Health Checker #1 Health Checker #2 Health Checker #3 Leader
 141.  Leader Election
 142.  여러 대의 서버 중에서 한대만 그 일을 하게 하고 싶을 때 (or 분산 Lock)
 143.  Leader Election 클라이언트들 간의 약속으로 정해둠.
144.  질문 #2을 다시 살펴보자 #1 ClientClient예약 Server 결제 Server 결제 Server 결제 Server 서버목록 정보를 바꿔서 재배포 하는 방법 결제 Server
 145.  그러면 사람 손이 들어갑니다.
146.  Cluster Membership  Cases API Server 가 추가/변경 되었다. Database Master 장비가 추가/변경되었다. Cache 장비가 추가/변경 되었다.  우리의 대응은? 목록을 추가하고, 배포해야 합니다. 목록만 추가하면 알아서 동작합니다. 장비만 추가하면 알아서 동작합니다.
147.  해당 노드의 Child 정보만 읽어와서 접속하면 목록 관리 가능
148.  Zookeeper Event Notification #1 zookeeper 예약 서버 예약 서버 예약 서버결제 서버 결제 서버 /znode/payment/ znode_0000001 znode_0000002 서버 시작시 /znode/payment/ 에 임시 노드 등록
149.  Zookeeper Event Notification #1 zookeeper 특정 znode 변경 서버 추가/삭제/변경 예약 서버 예약 서버 예약 서버결제 서버 #1 결제 서버 #2 /znode/payment/ znode_0000001 znode_0000002 결제 서버 #2 znode_0000003 특정 node 변경 이벤트 /znode/payment/ 를 다시 읽어서 서버로 접속
150.  용어  Release/Deploy/Delivery 새로운 기능을 출시/배포 하는 것을 의미  Rollback 새로운 기능 배포에 문제가 있을 때, 이전 버전으로 되돌리는 것을 의미
151.  질문  새로운 기능을 배포했는데, 문제가 발생했습니다. 해당 증상을 제거할 수 있는 방법에는 어떤 것들이 있을까요? Ex) 버그 수정 후 재 배포, 롤백
152.  질문  만약에 한번 배포할 때 마다 몇 시간씩 걸린다면?
153.  Feature Flag(Feature Toggle) 기능 Feature를 동적으로 끄고 켤 수 있는 방식 Ex) 카카오톡 대화방의 눈은 어떤 조건으로 내리기 시작할까? 이런 기능을 제공하기 위해서 준비해야 하는 것은?
154.  그러나 훨씬 중요한 것들
155.  좋은 엔지니어가 되기 위해서
156.  동료들에게 올바른 질문하기  질문을 하기 위해서…  문제의 증상을 정리  어떤 오류가 나오는지  자신이 정말 알고자 하는 것…  자신이 시도한 방법…
157.  올바른 답변 적용하기  알려준 방법으로 문제가 해결된다면  문제의 근본적인 원인은 무엇인가?  알려준 해결책은 어디에 적용되는가?  옵션을 추가하세요.  그 옵션을 알고만 끝날 것인가?  그 옵션이 어떻게 동작하는지를 완전히 이해하고 유사한 문제를 해 결 할 수 있을것인가?
158.  자동화(Automation)  사람의 손으로 반복해야 하는 부분들…  로그에서 특정 키워드 검색  특정 키워드 변환등  세번 이상 하게 되면, 자동화
159.  문서화와 공유  내가 문제를 해결한 것만으로는 모든 것이 해결될까?  내가 해결한 방법으로 팀의 누구나 해결할 수 있다면? 나는 이제 이 문제를 던지고 새로운 재미난 문제로…  문서화 원인/증상/해결책(Opertaion)  그리고 공유 발표 및 문서 위치 공유
160.  항상 호기심을 가지세요.
161.  Thank you.
 

반응형