중앙 서버 없는 게임 로직

Post on 16-Apr-2017

4.140 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

중앙서버없는게임로직<야생의땅: 듀랑고>

0. 듀랑고의서버

1. 실시간동기화

2. 농사와날씨

3. 협동건설

4. 사유지

5. 부족

최호영테크니컬디자이너, 8년차게임프로그래머

야생의땅: 듀랑고

“공룡시대야생환경에던져진현대인이되어,

로망있는생존,탐험,사냥,개척,사회건설을플레이하는

새로운체험의모바일MMORPG”비전게 임 의

탐험, 개척탐험의매력은이세상의모든곳을눈으로확인하고그곳에발자국을찍는것

개척의매력은주인이없는거친땅을다듬어나의소유로만드는것

넓은땅, 하나의세계되도록넓은땅을유저에게제공하고싶다

어떤유저든지원한다면서로만날수있게해주고싶다

분산서버안정성과부하의분산을위한구조부분적장애가전체서비스에영향을주지않음

듀랑고의서버

객체가중심이되는서버

• 하나의지역을물리적인서버가담당하는것은땅의크기가서버의성능에의해제한될수밖에없다

• 서버가어떤지역을담당하지않는다

• 서버는모종의규칙에의해배정된객체를담당한다

최적화에유리한방향으로

객체

다른서버의객체

각객체시야

각객체시야의합

다른서버객체의환영

엄밀하게는서버-서버간차이가아닌서버-클라이언트간차이지만이해를돕기위해가져옴

내가움직임➔서버에서처리해준결과

장점

서버에소속된객체의시야외에는관심이없어

전체세계의크기와상관없는구조

➔이론적으로무한한크기의세계를표현가능

특정서버에문제가생겼을때재접속하면

바로그위치에서정상적인플레이가능

➔안정성의향상

100 ㎢0.25 ㎢ 1 ㎢ 4 ㎢

836개의섬

2016년 4월 LBT 기준

실시간동기화

동기화

• 동기화가잦을수록 DB에부담이된다

• 동기화가잦을수록패킷량이늘어난다

• 지나치게잦은동기화는최적화의대상

• 하지만플레이가불가능하진않다

분산환경에서의동기화

• 객체에서환영으로서버간동기화가이루어진다

• 같은곳을보는서버가많을수록 N배부담

• 동기화에서느끼는부담이늘어났다

2015년 12월 LBT 1일차

• 오픈직후는괜찮은듯보임

• 접속자가늘어나자급격히서버랙증가

• 모니터링결과엄청난양의동기화감지

서버지연의원인

• 플레이어는이동할때마다조금씩에너지를깎는다

• 깎을때마다동기화가발생한다

• 이동하는모든플레이어가동기화를유발

• 30명의플레이어기준으로분당약 10000회의동기화를시도

최적화

• 동기화당부하를줄여보자• serialize, deserialize를가볍게하기• 최소한의정보만동기화

• 게임로직레벨의최적화는아닌것같다

동기화자체를줄여보자

회회1

1010초간초당 -1일때동기화횟수

1초마다 1씩에너지를감소시키는방법10초동안총 10의에너지를지속적으로감소시키는방법

➔ 아래방법이훨씬효율적이다. 그런데왜잘안쓰게될까?

x N

x N

10 15 20 30 초

10초부터 10초간초당 -1015초부터 10초간초당 +5

0초부터∞초간초당 +1

이걸언제다계산하고있어

what-studio/gauge

https://github.com/what-studio/gauge

변화량을입력하면그래프방식으로데이터를보여주는라이브러리

그래프동기화

(since, until, velocity),(since, until, velocity),

(since, until, velocity),

(광고) what-studio/gauge를이용하면당신도쉽게그래프동기화를 ...

그래프동기화

• 추가적인변화가생기면다시동기화해서덮어씌운다

• 현재시각(at)을넣으면언제어디서나현재값을알수있다

10 15 20 30 초

15초부터 10초간초당 +5

그래프동기화를쓸때주의할점

until이미정인경우가있다

➔움직이는동안에너지소비

➔접속중일때만피로도가오름

끝나는이벤트를잡는데실패하면영원히지속된다

변칙적운용

until을정해진시간만큼지정해둔다

일정시간마다 until을갱신한다

➔실수로이벤트를놓쳤다면 until만큼만동작

언제끝날지모르는이동중에너지소비문제해결

접속중일때만증가해야하는피로도문제해결

가까운미래의예측

수치의지속적인증감

상태효과로인한일시적인변화

일정시간동안모션의변화

• 언제부터(since) 언제까지(until) 변화가지속될지가명확하다

• 변화를매순간계산하지말고미리예측하여추이자체를동기화하자

플레이어 30명의분당동기화횟수이동중에너지감소문제수정후

5약 배절약1차와 2차 LBT의서버비용차이물론다른개선요소들도반영된결과긴하지만…

약10000회➔ 1000회이하

농사와날씨

신기루

자연물과건축물은

눈에만보이고실체가없다

신기루그리드

사과나무

갈대 갈대

갈대 갈대물물

물 자연물은위치와종류만저장

건축물은외형패킷을패킹하여저장

신기루의실체화

신기루와인터랙션을하는순간실체화

자연물은아무도건드리지않았을땐 DB에도존재하지않는다

신기루의장점

실체화한뒤에일정시간이지나도록인터랙션이없으면다시신기루화

➔메모리사용량을최소화

움직이지않는객체들도주변움직임에관심을가지고있음

➔메모리에있지않으면관심이없어지므로동기화비용감소

시간이변하면외형이변하는것들

외형이전부캐싱되어있기때문에난감한경우가있다

• 불타버린모닥불

• 내구도가다된건축물

• 다자란작물

• 외형캐시에만료시간을넣자

• 만료시간이지난캐시는버리고 DB에서정보를불러와새로생성한다

• 해당객체를보고있는모든서버에서각자알아서처리

• 외형캐시가교체되면연결되어있는클라이언트들에게전송

농사

70%토양적합성

• 작물이성공적으로자랄확률은유저의행동에의해서결정됨

• 하지만각처리를서버에서하기때문에서버마다결과가달라질수있다

70% 70% 70% 70%

!?

결정론적작물

언제어디서결과를확인하더라도같은결과가나와야한다

작물이다자라는시각을랜덤시드로하여결과를판별한다

Random(성장완료시각).random() = 0.751

0.751 ➔성공

70% 70% 70% 70%0.751 ➔성공 0.751 ➔성공 0.751 ➔성공

결정론적날씨

같은지역이면어떤서버에서도같은날씨여야한다

다른시간대면랜덤하게다른날씨일수있다

Random(지리적위치 + 현재시각 / 날씨변화주기).random()

➔시기적으로랜덤이지만지리적으로는언제나같은결과를얻어온다

협동건설

개척, 건설건설은개척의핵심요소

여럿이모여마을을이루고

사회를이룬다

건설현실속에서건설은제작/채집보다훨씬오래걸리는일

빠른건설허용은난개발을가져온다

시간은어느정도길게하지만협동을통해서극복할수있게하고싶다

원기옥의프로토타입

누군가가건설을시작하면동료들이옆에서같이건설을한다

여러명의건설력을합하여서완성하는속도가빨라진다

원기옥시스템에숨어있는피쳐들

건설할때는지속적으로에너지가감소

건설할때는지속적으로도구의내구도가감소

오래걸리는작업이므로잠시접속을끊어도건설은계속진행되도록

쉬운, 그러나할수없는방법

루프를돌면서

➔도구의내구도를깎고

➔플레이어의에너지를소모한후에건설의진행도를올린다

✘간단하지만장시간루프를돌려줄주체가없다

✘루프를통해서완성도를올리는방법은지속적인동기화를유발하기때문에최적화면에서좋지않다

여러개의서버가동시에관여중

그래프동기화의활용

건설력➔ velocity

도구의내구도 + 남은에너지➔ until

✔진행을처음부터끝까지그래프로나타낼수있다

✔참여자가새로참여할때마다그래프를새로그리면되...겠죠?

참여자중한명이참여를중단

➔ 완성이더늦어짐

➔ 남은참여자의에너지소모와, 도구의내구도소모가늘어남

➔ 모두의에너지소비그래프와내구도소모그래프를다시그린다

모든참여자의에너지소비그래프와내구도소비그래프를다시그린다

➔다시그리는중에누가또나가면?

➔다시그리던거마무리하고, 또 ... 다시그린다...➔근데참여자중한명이오프라인이라면?

무엇이혼란한가?

분산된환경에서는객체들이다른프로세스에흩어져있다

행동의여파가여러객체에동시에영향을주는경우적용에시간이걸린다

그행동이동시에여러곳에서요청이온다면?

심지어메모리에올라와있지도않은객체가포함되었다면?

디자인방향의선회

✘건설하는동안플레이어의행동을제한한다

✘게임진행의흐름을끊는다➔ 모바일게임의특성과맞지않다

앞에붙어서건설을하는시간자체는짧게하지만협동의느낌은나게

개선된원기옥

1명이건설 (짧은시간)

➔ 건축물이완성되기를기다림 (긴시간)

➔ 친구가 ‘도와주기’를하면기다리는시간감소

➔ 정해진시간이지나면완성

✔실제앞에붙어있어야하는시간이짧다

✔비동기적인액션으로동료가완성시간을줄여줄수있다

동시에여러객체를변조하는일은회피하자

2개이상의객체에동시에영향을주는작업은구현비용이비싸다

비싸게지불하고구현했더라도버그가능성이너무높다

유지보수도복잡하다

디자이너와충분한협의를통해디자인자체를회피하는방향으로선회하자

사유지

사유지

@YoshiCoin 님의만화

사유지권한

친구 / 외부인 / 부족원(추후제공예정) 에게권한을일부혹은전부허용해줄수있다

가족간에도범죄가생기는무서운시대

내사유지에서무슨일이일어나는지나는알아야겠다!!

ytn

newsis

데일리한국

오마이뉴스

사유지이력시스템

실시간알림의필요성

• 이력시스템은문제를발견하기전까지이용하지않게된다

• 문제를발견한이후에는늦을수있다

• 내사유지에서일어나는행동에대한빠른피드백을위해실시간으로알림이필요하다

오프라인인캐릭터에게알림

• 접속중일때는해당캐릭터에게알림을보내면그만

• 접속중이아닐때는어떻게해야할까?

• 해당캐릭터의 DB 속데이터를직접수정해야한다

• 여러명이동시에사유지에서활동할경우동시에알림을보낼수도있다

• 여러명의요청을안전하게처리할수있어야한다

요청자가서로다른서버에있을수있음

낙관적트랜잭션

니가알고있던건최신이아니야

동작이단순하고가볍다하나의문서만을대상으로할수있다

낙관적트랜잭션의어려움

트랜잭션시수행하는코드는언제나재실행이가능해야한다

실행은사이드이펙트가없어야한다

객체는복잡하고다양한로직을가지고있다

객체를대상으로는낙관적트랜잭션을금지

사이드이펙트가누적될수있다

계속해서다시시도해야할수있다

객체의소유권

• 서버에게객체의담당시킬뿐아니라소유권한까지넘긴다

• 어떤객체에게영향을주고싶으면소유한서버에게문의해야한다

• 하지만접속중이아닐때에는?

DB에태스크큐

객체마다태스크큐를 DB에만든다

작업을큐잉해둔다

owner.queue_task(

Player.notify_estate_event, *args, **kwargs)

그객체가접속중이라면 rpc를통해서알려준다

접속중이아니었다면접속할때내큐를확인해서수행한다

사유지알림

• 행동을하는객체는사유지의주인에게꼬박꼬박보고를한다

• 오프라인일때일어났던일은접속할때알려주고

• 온라인일때일어난일은바로알려준다

부족

부족시스템아직시스템에서지원을하고있진않음

기반은작업해두었지만더완성도를높여서보여드리고싶은마음에아직공개한적은없음

부족과플레이어의관계는서로참조

가입이나탈퇴는양쪽문서를모두수정해야한다

d부족 A

c

a

b

가입과탈퇴시양쪽문서가동시에수정됨이보장되지않는다면

예상할수없는문제들이속출

d부족 A

c

a

b

ACID 트랜잭션

• 안전한트랜잭션을위한특징

Atomicity 부분적으로만실행되지않는다

Consistency 실행에성공하면언제나일관된상태로유지된다

Isolation 수행중다른트랜잭션이끼어들수없다

Durability 성공한트랜잭션은영구히반영된다

• 하지만우리는분산에더적합한 NoSQL을사용

• NoSQL에서는보장하기힘들다

BASE 트랜잭션

• ACID를 NoSQL에서근사하게보장해주기위한애플리케이션레벨의방법

Basically AvailableSoft stateEventual consistency

• 트랜잭션에내용을따로문서로작성

• 애플리케이션레벨에서해당문서를참조하여결과적으로일관성을보장함

• 애플리케이션레벨의처리이기때문에로직자체에서신경써야할점이많다

가입과탈퇴

가입과탈퇴는두개의문서를동시에수정하는작업

하지만 BASE 트랜잭션은고민을많이해야하고구현이복잡하다

BASE 트랜잭션을안쓰고낙관적트랜잭션만으로해결할순없을까?

가볍지만하나의문서를대상으로만가능

가입신청

가입을신청할때부족문서에기록하지말자➔낙관적트랜잭션만으로가능

플레이어가부족을가리키는단방향관계형성DB에쿼리를통해서부족은가입하길원하는플레이어를검색

가입과강제퇴출

부족장이가입을승인할땐부족이플레이어를가리키게한다

➔낙관적트랜잭션만으로가능

부족장이부족이플레이어를가리키지않게하면강제퇴출

하지만이럴경우가입신청한상황과구분이되지않는다!

토큰의도입

가입신청과수락시에토큰을같이기록한다

토큰은유니크한값이발급된다

A17D3

A17D3

강제퇴출

강제로퇴출시에는토큰을만료만시킨다

양쪽토큰이일치하더라도토큰이만료되었을경우는인정하지않는다

A17D3

A17D3:만료됨

4F82K

탈퇴

자진탈퇴할때는조용히나의가리킴만삭제기존의부족쪽토큰은데이터는있지만사실상의미가없다

재가입신청을할때는토큰이바뀌어있으므로기존의부족쪽토큰은무효

A17D3

초대

• 초대를보낼때에는부족쪽에서발행하여토큰을초대장과함께보낸다• 초대장을보내는순간이미부족은플레이어를가리키고있다

• 내가해당토큰으로부족을가리키면초대수락

A17D3

A17D3

낙관적트랜잭션만으로해결

가입신청/ 탈퇴/ 초대수락➔플레이어데이터만수정

가입수락/ 강제탈퇴 / 초대➔부족데이터만수정

일반적인로그인세션과다르지않다

간단한구조변경을통해가벼운낙관적트랜잭션으로해결

중앙서버없는게임로직

중앙서버가없다는것은?

원탁의기사는보기에는좋지만

실제로는일의절차가복잡하고느릴수있다

이미활용되고있는서비스형태

• 이미웹서비스외여러분야에서다양하게활용되고있다• 서비스의안정성과가용성을위해선어쩌면당연한선택

• 단지 MMORPG에서활용된적은많지않은것같다

오늘소개한전략들도상당수여기서힌트를얻음

분산구조에대응하는전략

• 복잡한계산은최대한한곳에서, 다른서버에서는결과만받아보자

• 모든서버에서계산은해야한다면어디에서하든지 결과가동일하게

• 동기화를최대한하지않는다

• 다른서버의객체에동시에적용되어야하는작업을최소화한다

시행착오

• 처음엔별생각없이익숙한방식으로작업하다가재작업을많이함

• 일반적인멘탈구조와달라작업할때조심을많이해야함

하지만오늘살펴본사례에서볼수있듯이생각보다해결방법은간단하고일반론안에서해결이가능하다

고비용 = 적응비용

많은사람이시도하여이미다양한경험이공유되어있었다면우리도시행착오를줄일수있었을것같습니다

Q

A

감사합니다

Q&A

NDC16 <야생의땅: 듀랑고>의거친환경에서살아가는동물 AI

세션에서설명드린것을참고하시면좋을것같습니다.

저희는 PVE와 PVP 모두콜로세움이라는노드를통해해결합니다

모든전투와관련된행동들이해당노드에서결정, 수행되기때문에

전투에관해서만큼은다른서버에있다고하여시간차가발생하지

않습니다

Q

A

만약 PVP가구현된다면, 예측불가능한인터랙션이매우많이발생하여서로다른서버에있는유저들사이에서많은부담이발생할것같습니다. 혹시구현계획과그대책이있나요?

여러플레이어들과공룡을사냥할때신속한동기화가필요할텐데이럴경우동기화의퍼포먼스, 그리고말씀하신동기화로인한부하가커질텐데그런부분은어떻게해결하셨나요?Q

객체는서버에게소유권이이전되어있기때문에

다른서버에있는객체둘이어느목표대상물에게접근하려면

둘다목표대상물을소유한서버에 rpc를통해서

요청을보내는수밖에없습니다.

해당서버안에서는객체단위로 rpc 요청이직렬화되기때문에

요청받은순서대로처리하게됩니다.

QA

동시에다른서버에있는유저가같은객체와인터랙트하는경우에는두유저가모두인터랙트를할수있는지? 동기화는어떻게처리되는지요?

병목이생기는부분을분산할예정입니다.

QA

서버간동기화로인해패킷이늘어나면, 물리적네트워크처리량이병목이되지않나요? 패킷양으로인해물리적네트워크처리량에병목이온다면, 어떻게해결할계획이신가요?

인스턴트를새로만드는비용은언제나최소한으로맞추기위해

노력을했습니다. 기본적인정보만미리세팅하고상세한정보들은

필요할때만들거나읽어오도록하였기때문에코스트가

크지않습니다

QA

신기루그리드를누군가터치했을때인스턴스를새로만든다면새로만드는연산에비용코스트가크지않나요?

서버는지리적으로는영향력이없기때문에문제가생긴서버에게

속한객체가정상적으로동기화되지않는다는문제점정도는

있을것이지만, 그지역자체에는아무런영향이없습니다.

QA

특정서버만이오류가있을때게임지리적으로같은곳에객체가존재하는다른서버도같이영향을받을텐데이는어떻게해결하실생각인가요?

아직글로벌서비스에대한준비가완벽하지않아서

확실하게답변드릴수있는부분이아닌것같습니다.

모바일통신환경에서는기본적으로 latency가클수밖에없기때문에

항상높은 latenc를가정하고게임을디자인하고있습니다.

QA

서로다른지역에서플레이하는사람은해당지역의서버에접속을하나요? 그렇다면서버간통신 latency가큰경우에어떤문제가생길수있나요?

최초로 active 상태가되는것은유저의선택 (인터랙션)에의해서

이루어집니다. 단순히내부적상태가변하는것은저희도이때

처리하고있습니다만, 이세션에서설명드린부분은시간에따라

외형이변하는객체들입니다. 모닥불이활활타고있는것같지만

실제로는꺼져있는상태는유저에게혼란을줄수있어그렇게할수

없었습니다.

QA

시간에따라상태가변경되는지형물은스케줄러에등록해놓고매번처리하지말고, 최초로 active상태가될때누적된처리를한번에해주면어떤문제가있나요?

일단분산된서버라는것자체가원래있던서버에접속할필요가

없게만들어야합니다. 재접속할때에는원래접속했던서버에

접속할확률이낮기때문에언제나관련된정보는 DB에저장해두고필요할때마다꺼내기쉽게해놓았습니다.

Q

A

중앙서버가없다면비원활네트워크상황이발생했을경우, 원래로그인했던게임서버에재접속이된다는보장이없을텐데, 다른게임서버에재접속됐을경우예전게임서버에남아있는유저의정보와, 새로로그인되는유저의정보는어떻게처리되는지궁금합니다.

유저의이동은 BASE 트랜잭션으로저장하지않고각소유권이인정된서버에서알아서처리하기때문에

Eventual consistency 로처리하지않습니다.

그리고각개체는겹쳐있는것을허용하기때문에충돌이일어나지

않습니다.

QA

서로다른서버에있는두유저가동시에같은장소로이동할경우Eventual Consistency로처리되면위치가충돌하지않을까요?

쉽게답변드릴수없는부분인것같습니다.

QA

듀랑고정도의서버프로그래밍의예상개발시간소요는어느정도일까요

iOS 노티피케이션은큐를통해서처리하지않습니다.큐에작업을넣을때필요한경우푸쉬(노티피케이션)을따로

보내고있습니다.

QA

오프라인인유저가접속해야있던큐를처리하면, 오프라인인유저는 iOS 노티피케이션을받을수없나요?

누군가가해당지역을처음으로목격했을때로드됩니다.

해당서버에서그지역에관심있는객체가하나도존재하지않게되면

다시누군가목격할때까지는메모리에서해제합니다.

QA

외형캐시가서버에로드되는시점이언제인가요?

DB의특정노드에장애가난상태에서일부 DB 작업이실패하는데전체서비스가망가지진않지만일부동작이망가질순있습니다.

DB 자체는 persistent 합니다.

Q

A

오프라인유저에대한지연된업데이트를위해 DB큐를둔다고하셨는데요. 해당큐에장애가나는경우에도대비되어있나요?

오프라인유저의지연업데이트를위한 DB큐도백업이있나요? 해당 DB큐에장애가나면데이터가날아가버리지않나요?Q

게임서버는파이썬으로만구성되어있습니다.

게임서버이외의워커들엔 C#도쓰고있습니다.

QA

듀랑고서버는파이썬으로만구성되어있나요?

네그렇습니다. 다만 3로옮기는것을고려중입니다.

QA

파이썬 2.7에 gevent를계속사용하고있나요?

파이썬의라이브러리생태계가아주잘이루어져있기때문이었습니다

QA

서버개발언어로분산에최적화된여러언어가아닌(얼랭이라던가) 파이썬을고른이유는무엇인가요?

저희는 NoSQL인 Couchbase를사용하고있습니다.

QA

db는 awa의 rds를쓰시나요? 다이나모를쓰시나요 rds를쓰신다면어떤엔진을쓰시고그엔진을쓰신이유가있다면?

네그렇습니다.

QA

사용하는파이썬구현체는무엇인가요? (only cpython?)

아직확정되지않은부분이라답변드리지못함을양해부탁드립니다.

QA

랭킹시스템이들어간다면어떻게구현을하실생각인가요?

top related