Top Banner
분분 분분 분분 분분분 분분분 분분분
35

KGC 2014: 분산 게임 서버 구조론

Jun 23, 2015

Download

Documents

Hyun-jik Bae

분산 서버 설계는 원리 이해가 중요하다. 이를 모르고서는 잘못된 설계로 인해 고생은 고생대로 하고 결과는 결과대로 나쁠 수 있다. 본 강연에서는 분산 게임 서버 구조를 짜기 전에 반드시 이해해야 하는 원리를 설명한다.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: KGC 2014: 분산 게임 서버 구조론

분산 게임 서버 구조론넷텐션배현직

Page 2: KGC 2014: 분산 게임 서버 구조론

알아야 할 용어

Page 3: KGC 2014: 분산 게임 서버 구조론

5000 10000 15000 200000

200

400

600

800

1000

1200

1400

성능만 좋음 확장성만 좋음

동시접속자플

레이

어당

처리

시간

서버의 성능 ? 확장성 ?

• 서버의 성능과 확장성은 서로 별개

사업계획서 Part 2 page 1

Page 4: KGC 2014: 분산 게임 서버 구조론

확장성을 위한 방법

Page 5: KGC 2014: 분산 게임 서버 구조론

Scale-up vs. scale-out

Scale-up ( 수직적 확장 ) Scale-out ( 수평적 확장 )

확장의 종류 서버 머신의 부품을 업그레이드 혹은 서버 머신 안의 CPU, RAM 을 증설

서버 머신의 수를 증설

서버 소프트웨어 설계 비용 낮음 높음

확장 비용 높음 ( 기하급수적으로 높아짐 ) 낮음 ( 선형적으로 높아짐 )

과부하 지점 서버 컴퓨터 자체 네트워크 장치

오류 가능성 낮음 ( 로컬 머신 내에서 동기 프로그래밍 방식으로 작동하므로 )

높음 ( 여러 머신에 걸쳐 비동기 프로그래밍 방식으로 작동하므로 )

단위 처리 속도 높음 ( 로컬 컴퓨터의 CPU 와 RAM 만을 사용 ) 낮음 ( 여러 서버 컴퓨터간의 메시징이 오가면서 처리하므로 )

처리 가능 총량 낮음 ( 서버 컴퓨터 1 개의 성능만을 사용하므로 ) 높음 ( 여러 서버 컴퓨터로 부하가 분산되므로 )

Page 6: KGC 2014: 분산 게임 서버 구조론

서버 분산이 없다면 ?

Page 7: KGC 2014: 분산 게임 서버 구조론

전혀 분산되어 있지 않은 서버

• 모든 게임서버 로직은 1 개의 서버 프로세스에서 수행• 모든 플레이어 정보는 1 개의 데이터베이스에 저장

Client Server Data-base

Page 8: KGC 2014: 분산 게임 서버 구조론

동시접속자가 무제한으로 증가할 경우 발생하는 현상 ( 클라이언트 )

• 서버로 보낸 메시지에 대한 처리 응답이 늦게 도착함• 서버로의 접속 과정이 매우 오래 걸림• 서버와의 연결이 돌발 해제됨

– TCP retransmission timeout 으로 인해– 사용자 정의 keep alive 메시징의 타임아웃으로 인해

• 서버로의 접속 자체가 실패함 ( 타임아웃 )

Page 9: KGC 2014: 분산 게임 서버 구조론

서버에서의 현상

• CPU 사용량이 증가• 클라이언트로부터 메시지를 받는 속도보다

메시지를 처리하는 속도가 느린 경우 RAM 사용량이 증가

• 클라이언트에게 보낼 메시지의 발생 속도보다 실제로 메시지를 보내는 속도가 느린 경우 RAM 사용량이 증가

• 즉 , CPU 의 과부하는 RAM 사용량 증가로 이어짐

시간 1 시간 2 시간 3 시간 405

1015202530354045

Chart Title

메시지 수신 메시지 처리 메모리 사용량

Page 10: KGC 2014: 분산 게임 서버 구조론

• x86 의 경우 : RAM 의 사용량이 계속해서 증가하다가 , 2~3GB 프로세스 메모리 사용 상황에서 malloc() re-turns null 이 발생

• x64 의 경우 : 서버 물리적 메모리보다 더 많은 양의 메모리를 할당하게 되면서 대량의 memory swapping이 발생함 . 이로 인해 프로그램 실행 속도가 급락하면서 메모리 할당량이 더욱 증가하는 악순환 발생

• Disk 의 최대 처리속도를 상회하는 Disk I/O 를 요구하는 명령 (DB query) 이 데이터베이스에 쌓이면서 RAM 사용량이 증가하다가 상기와 같은 문제가 데이터베이스에서도 발생

• 게임 컨텐츠의 구성에 따라 다르나 , MMORPG 의 경우 동시접속자 2 만명이 넘어가면 이러한 문제가 쉽게 발생

int* a = malloc(1000);// access violation if a is nulla[0] = 1;

// throws bad_alloc if no more memoryMyClass* b = new MyClass();

Page 11: KGC 2014: 분산 게임 서버 구조론

네트웍 장치에 과부하가 걸리면

• 원래 , 무선 네트워크나 개발도상국의 클라이언트 쪽에서 발생하는 현상

• 클라우드 서버의 가상 라우터 소프트웨어의 과부하로도 발생함

• 라우터 과부하로 인해 , packet drop 발생• TCP retransmission timeout 으로 인한 TCP

disconnection 발생

Page 12: KGC 2014: 분산 게임 서버 구조론

서버 분산 방법

Page 13: KGC 2014: 분산 게임 서버 구조론

간단한 서버 분산 방법

• 게임 서버와 데이터베이스로 구성된 세트 ( 서버 채널이라고도 부름 ) 를 쭈욱 나열하는 것만으로도 간단히 해결됨

• 계정 인증 부분은 게임 퍼블리셔에서 알아서 대규모 처리를 할 수 있게 해놓았으므로 문제를 회피함

• 게임 서비스는 국가별로 다름– 따라서 계정 인증 담당 서버와 장치들도

전세계 여러 곳으로 나뉨– 따라서 유저 밀집으로 인한 과부하를

회피 가능

Server Data-base

ClientSwitch, routerFirewall

Server Data-base

Server Data-base

Server Data-base

AuthServer

Auth Database

Page 14: KGC 2014: 분산 게임 서버 구조론

• 이 방식의 문제점– 같은 계정이라도 플레이어 정보가 서로 다른

서버 채널에 다르게 존재함 . – 즉 플레이어는 자기 캐릭터 등의 정보를 알기

위해 자신이 플레이했던 서버 채널을 알고 있어야 함

• 모바일 게임과 글로벌 서비스 게임에서는 이러한 서버 채널이 없어지는 것이 추세

• 논리적 단일 서버의 필요성 대두

Page 15: KGC 2014: 분산 게임 서버 구조론

논리적 단일 서버를 분산하기

Page 16: KGC 2014: 분산 게임 서버 구조론

서버의 각 부하 지점

• 서버의 각 지점의 최대 처리량 예시– Router, switch : 1GB/sec– Firewall: 500MB/sec– CPU: 4 core * 3GHz– Storage: 100MB/sec (SSD), 10MB/sec (HDD)

• 동시접속자가 증가하면서 , 위 4 가지 자원의 사용량은 한계에 점점 가까워짐– 한계에 빨리 부딪히는 것을 우선으로 해결해야 함– 4 가지 자원의 한계를 모두 해결하는 것이 궁극적인 해결책이지만 , 통상 온라인 게임의

경우 2 가지 정도만 해결해도 충분하기도 함

Server Data-base

Client Switch, router

Fire-wall

Page 17: KGC 2014: 분산 게임 서버 구조론

서버의 과부하 지점을 찾는 방법

• 서버의 과부하 지점을 찾는 현실적인 ( 그러나 비경제적인 ) 방법– Scale-out 을 전혀 고려하지 않은 서버를 먼저 개발한 다음 ,– 동시접속자를 증가시키면서 부하 지점의 처리량을 측정하기

• 측정하기 위해 , code profiler와 DB query profiler 등을 사용– 접속자가 늘어날수록 부하가 가파르게 증가하는 요소를 찾아 , 해당 요소를 scale out 으로

재개발을 한다 .

• 서버의 과부하 지점에 대한 경험이 있을 경우 미리 scale out 으로 개발하면 더욱 경제적

• 서버의 과부하 지점의 예– 몬스터가 많이 등장하는 필드– 플레이어가 많이 몰리는 광장– NPC 의 AI 처리 (path finding)

Page 18: KGC 2014: 분산 게임 서버 구조론

이렇게 해서 서버의 과부하 지점을 찾은 후에는 어떻게 분산할 것인가 ?

Page 19: KGC 2014: 분산 게임 서버 구조론

데이터 분산 vs. 기능적 분산

• 데이터 분산– 한 머신이 처리해야 하는

데이터를 동일한 역할을 하는 여러 머신들이 나누어서 처리

– 시계 공장에 비유하자면 , 각 제작자가 부품 조립 , 도색 , 포장을 모두 수행하되 이러한 사람들이 다수 포진 재료

부품 조립 , 도색 ,포장

부품 조립 , 도색 ,포장

부품 조립 , 도색 ,포장

부품 조립 , 도색 ,포장

상품

Page 20: KGC 2014: 분산 게임 서버 구조론

• 기능적 분산– 한 머신이 처리해야 하는

데이터의 처리 단계를 세분화해서 여러 머신들이 나누어서 처리

– 시계 공장에 비유하자면 , 제작의 각 단계를 서로 다른 사람이 수행

• 데이터 분산과 기능적 분산을 혼용하는 것도 가능

재료 상품

부품 조립

도색

포장

Page 21: KGC 2014: 분산 게임 서버 구조론

분산된 서버에서의 게임 로직

Page 22: KGC 2014: 분산 게임 서버 구조론

상호작용 시나리오 예시

• 플레이어 캐릭터가 몬스터 캐릭터를 죽이고 , 아이템을 획득하기– 플레이어가 가진 총알 1 개를 소모– 몬스터의 체력을 깎음– 몬스터의 체력이 바닥나면– 몬스터 사망 (10초후 소멸 )– 플레이어는 아이템 획득

• 단일 서버라면 이러한 상호작용은 우측과 같이 구현될 수 있음

• 상호작용의 두 개체 (player, monster) 는 같은 메모리 공간 즉 서버 프로세스 안에 존재할 때 실행 가능함

Player_Attack(player, monster){ player.bullet--; monster.hitPoint-=10; if(monster.hitPoint<0) { player.item.Add(gold, 30); DeleteEntity(monster, 10sec); }}

서버 1

PlayerMonster

서버 2

Page 23: KGC 2014: 분산 게임 서버 구조론

• 만약 player, monster 가 서로 다른 서버 프로세스에 분산되어 있는데 이들간의 상호작용을 반드시 해야 할 경우 어떻게 해야 할까 ?

• 3 가지 방법이 존재함– 동기 분산 처리– 비동기 분산 처리– 데이터 복제 (replication) 에 기반한 로컬 처리

서버 1

Player

서버 2

Monster

Page 24: KGC 2014: 분산 게임 서버 구조론

동기 분산 처리

• 어떠한 연산을 다른 서버에 던져놓고 , 그 결과가 올 때까지 대기를 하고 있음– 대기할 뿐만 아니라 , 그 연산과 관계된 데이터가 도중에 변경되지 않도록 lock 을 하고 있어야 함

• 단위 처리의 시간이 길어지는만큼 lock 영역이 발생시키는 처리성능 병목 문제도 발생함

Player_Attack(player, monster){ lock(player) { player.bullet--; e = otherServer.DamageCharacter( player.id, monster.id, 10); waitForResult(e); if (e.hitPoint < 0) { player.item.Add(gold, 30); }}

DamageCharacter(attacker, character, dam-age){ character.hitPoint-=damage; result.hitPoint = character.hitPoint; Reply(result);}

1. 요청3. 응답

2. 대기 발생 !

Page 25: KGC 2014: 분산 게임 서버 구조론

처리성능 병목 문제의 심각성

• 암달의 법칙– 병렬 처리할 수 있는 장치에서 , 병렬로 처리하지 못하는 시간에 크게 비례해서 병렬 효과가 급감하는 현상

– 암달의 저주라고도 부름

• 따라서 동기 분산 처리의 잘못된 사용은 분산 서버의 효과를 떨어뜨릴 수 있음

병렬로 처리하지 못하는 시간 (붉은색 ) 의 비중이 클수록 병렬 처리 효과는 크게

감소함

Page 26: KGC 2014: 분산 게임 서버 구조론

비동기 분산 처리

• 어떠한 연산을 다른 서버에 던져놓고 그 결과를 기다리지 않고 일방적으로 다음 처리를 수행

• 단위 처리의 시간이 길어지는 만큼 병목 문제가 발생하는 일은 없음

• 그러나 , 로직의 구현에 한계가 발생함– 리턴값 없는 함수만으로 로직을

구현하는 것과 유사함– 리턴값을 반드시 받아야 다음 진행이

가능한 로직을 구현할 때 한계에 부딪힘

Player_Attack(player, monster){ player.bullet--; otherServer.DamageCharacter(player.id, monster.id, 10); }

DamageCharacter(callerServer, attacker, character, dam-age){ character.hitPoint-=damage; if(character.hitPoint<0) { callerServer.GiveItem(attacker.id, gold, 30); DeleteEntity(character, 10sec); }}

GiveItem(character, item, amount){ character.item.Add(item, amount);}

메시징

메시징

Page 27: KGC 2014: 분산 게임 서버 구조론

비동기 분산 처리 , 동기 분산 처리의 단점

• 비동기 분산 처리 , 동기 분산 처리 모두 어떠한 연산이 여러 서버에 걸쳐 처리되기 때문에 , 그 과정에서 머신간 송수신 과정이 들어가게 됨

• 네트웍으로 메시지를 보내는 데 걸리는 CPU 연산량과 network device I/O 처리에 걸리는 연산량은 수만 clock cycle 을 소모

• Switch 를 거치는 동안에도 딜레이가 밀리초 단위로 발생

• TCP 를 통해 전송하는 경우 nagle algorithm에 의해 밀리초 단위의 시간이 소모됨

• 즉 지나치게 분산 처리 단계가 많을수록 배보다 배꼽이 큰 사태가 발생

Socket IO call

OS File Plexer

OS layer

Network device driver

Device I/O

SwitchRouter

Socket IO call

OS File Plexer

OS layer

Network device driver

Device I/O

Page 28: KGC 2014: 분산 게임 서버 구조론

데이터 replication 에 기반한 로컬 처리

• 각 서버 프로세스는 데이터들이 변할 때마다 다른 서버들에게도 그 변화를 나머지 서버들에게 지속적으로 전송 (replicate)

• 따라서 각 서버 프로세스는 데이터 사본 (replica) 을 가지고 있음

• 이러한 전제하에 어떠한 연산을 할 때는 프로세스 내의 원본 ( 자기 서버에서 연산되는 데이터 ) 와 사본 ( 다른 서버로부터 받은 데이터 ) 를 가지고 연산을 수행

• 병목도 없으며 , 여러 머신에 걸쳐 연산하지 않으므로 응답 속도도 분산하기 전과 동일하게 빠름

• 그러나 , 사본 데이터는 원본 데이터와 간발의 순간 ( 밀리초 ) 으로 차이가 있을 수 있기 때문에 (stale data problem) 이때 데이터를 모두 신뢰할 경우 데이터 불일치로 인한 잘못된 연산 ( 하이젠버그) 이 발생할 수 있음

Player_Attack(player, monster){ player.bullet--; monster.hitPoint-=10; if(monster.hitPoint<0) { player.item.Add(gold, 30); DeleteEntity(monster, 10sec); }}

이 연산을 신뢰할 수 없을 수도 있음

Page 29: KGC 2014: 분산 게임 서버 구조론

응집도 낮은 데이터만 서로 다른 서버로 분산하기

• 분산하는 데이터의 단위가 지리적 영역을 기반으로 할 경우 , player 와 monster 는 대부분의 경우 ( 혹은 항상 ) 같은 서버 프로세스에 있게 된다 .

• player 와 monster 가 서로 같은 서버 프로세스 안에 있으면 안전한 상호작용 구현은 쉬워짐

• 온라인 게임들의 월드가 완전히 격리된 여러 지역으로 나뉘어있는 이유 중 하나는 서버 분산을 지리적 영역이라는 데이터 분산을 했기 때문

Page 30: KGC 2014: 분산 게임 서버 구조론

기능적 분산 처리

• 데이터 처리를 서로 다른 서버를 거쳐가면서 처리하기

• 데이터 분산 처리를 할 수 없는 경우의 대안예 : 경매장 서버 – 입찰 경쟁과 낙찰 과정이 atomic 하게

이루어져야 하기 때문에 경매장 서버의 거래 처리는 여러 서버가 데이터 분산하기 어려움 .

– 대신 경매장 서버는 경매장 처리만을 전담하여 다른 부하를 제거

• 서비스 품질 저하의 영향을 줄이고자 할 때도 기능적 분산 처리가 도움되기도 함– 예 : 채팅 서버와 전투 처리 서버를 분리하는 경

우 , 전투 처리 서버에 과부하가 걸려도 채팅 기능은 원활하게 작동함

• 기능적 분산 처리는 데이터 분산 처리보다 분산 유연성이 떨어짐– 기능 A,B,C중 B 에만 과부하가 걸릴 경우 ?

• 기능적 분산 처리에서 한계에 부딪히는 경우 해당 기능을 데이터 분산 처리로 다시 세분화가 가능한 경우도 있음

게임 서버

경매장 서버게임

서버

게임 서버

채팅 서버

클라이언트

클라이언트

클라이언트

Page 31: KGC 2014: 분산 게임 서버 구조론

지나친 분산 처리는 피해야

• 지나친 분산 처리 네트워크 장비에 부하 몰림네트워크 장비 과부하로 인한 서비스 장애– 네트워크 장비는 쉽게 과부하에 걸리지

않지만 일단 걸리면 해결이 어려움

• 분산 처리 프로그램은 디버깅이 까다로움– 여러 프로그램에 원격 디버깅 ?– 로그 출력을 보고 암중모색하기

Page 32: KGC 2014: 분산 게임 서버 구조론

분산 처리의 전략

• 데이터의 응집력을 확인하자– 다룰 데이터간의 상호작용이 높은 것들은 분산하지 말고 , – 다룰 데이터간의 상호작용이 매우 적은 것들만 골라 분산하자 .

• 즉 , 응집력이 높은 데이터를 구별하는 기준이 무엇이 될까 ? 를 찾자 .– 게임 월드 내 지리적 구분 ? (MMORPG 의 예 )– 플레이어의 레벨이나 등급에 따른 구분 ? ( 매치메이킹 시스템의 예 )

• 분산 처리 방식으로 가능하다면 다음 순으로 가능한 방법을 찾도록 하자– 데이터 동기화에 기반한 로컬 처리– 비동기 분산 처리– 동기 분산 처리

• 분산 처리 자체는 구현과 디버깅이 까다롭고 불필요한 과부하를 일으킴 불필요한 분산 처리를 피해야 하는 이유

Page 33: KGC 2014: 분산 게임 서버 구조론

분산 서버의 또다른 장점

• 확장성 뿐만 아니라 안정성에도 효과– 데이터 분산 서버의 경우

• 중지된 서버가 처리하는 데이터는 전체 플레이어 중 일부의 데이터일 뿐이기 때문에 서비스 장애 영역이 전체로부터 국소로 줄어듦

• 예 : 전체 플레이어의 20% 만이 접속이 끊어지나 다시 접속해서 게임 재시작 가능– 기능적 분산 서버의 경우

• 중지된 서버가 처리하는 기능 외의 다른 기능은 정상 작동하고 있기 때문에 서비스 장애로 인한 불편함이 줄어듦

• 예 : 게임 내 NPC 들이 모두 사라졌지만 PVP 와 채팅은 가능함 . 조금 있다가 다시 NPC 들이 상태 리셋 상태로 등장함

Page 34: KGC 2014: 분산 게임 서버 구조론

Scale-out 관련 용어

• Load balancing ( 부하 분산 )– 클라이언트의 네트워크 연결을 여러 서버 머신으로 분산해서 처리하기

• 컴퓨터 클러스터– 여러 대의 컴퓨터들이 연결되어 하나의 시스템처럼 동작하는 컴퓨터들의 집합– 즉 scale-out 의 결과물이 클러스터

• Fail-over– 동일한 역할을 하는 서버 컴퓨터 중 하나가 죽더라도 다른 서버가 즉시 역할을 대행– Active-active: 동일한 역할을 하는 서버 컴퓨터가 2 개 – Active-passive: 서버 1 대만이 역할을 수행하고 나머지 서버는 대기하고 있다가 첫번째

서버가 죽으면 역할을 대행 ( 그동안 죽은 첫번째 서버는 점검 후 재시작 )

Page 35: KGC 2014: 분산 게임 서버 구조론

마무리

• 성능 vs. 확장성• Scale up vs. out• 서버 과부하가 발생하면 나타나는 현상• 논리적 다중 서버 vs. 논리적 단일 서버• 서버 분산의 필요 지점 찾기• 데이터 응집력 식별하기• 데이터 분산 vs. 기능적 분산• 동기 분산 처리 vs. 비동기 분산 처리 vs. 데이터 복제 후 처리