43. • 작물이 성공적으로 자랄 확률은 유저의 행동에 의해서 결정됨
• 하지만 각 처리를 서버에서 하기 때문에 서버마다 결과가 달라질 수 있다
70% 70% 70% 70%
!?
44. 결정론적 작물
언제 어디서 결과를 확인하더라도 같은 결과가 나와야 한다
작물이 다 자라는 시각을 랜덤 시드로 하여 결과를 판별한다
Random(성장 완료 시각).random() = 0.751
0.751 ➔ 성공
70% 70% 70% 70%
0.751 ➔ 성공 0.751 ➔ 성공 0.751 ➔ 성공
45. 결정론적 날씨
같은 지역이면 어떤 서버에서도 같은 날씨여야 한다
다른 시간대면 랜덤하게 다른 날씨일 수 있다
Random(지리적 위치 + 현재 시각 / 날씨 변화 주기).random()
➔ 시기적으로 랜덤이지만 지리적으로는 언제나 같은 결과를 얻어온다
50. 원기옥 시스템에 숨어있는 피쳐들
건설할 때는 지속적으로 에너지가 감소
건설할 때는 지속적으로 도구의 내구도가 감소
오래 걸리는 작업이므로 잠시 접속을 끊어도 건설은 계속 진행되도록
51. 쉬운, 그러나 할 수 없는 방법
루프를 돌면서
➔ 도구의 내구도를 깎고
➔ 플레이어의 에너지를 소모한 후에
건설의 진행도를 올린다
✘ 간단하지만 장시간 루프를 돌려줄 주체가 없다
✘ 루프를 통해서 완성도를 올리는 방법은
지속적인 동기화를 유발하기 때문에 최적화면에서 좋지 않다
여러 개의 서버가 동시에 관여 중
52. 그래프 동기화의 활용
건설력 ➔ velocity
도구의 내구도 + 남은 에너지 ➔ until
✔ 진행을 처음부터 끝까지 그래프로 나타낼 수 있다
✔ 참여자가 새로 참여할 때 마다 그래프를 새로 그리면 되...겠죠?
53. 참여자 중 한 명이 참여를 중단
➔ 완성이 더 늦어짐
➔ 남은 참여자의 에너지 소모와, 도구의 내구도 소모가 늘어남
➔ 모두의 에너지 소비 그래프와 내구도 소모 그래프를 다시 그린다
54. 모든 참여자의 에너지 소비 그래프와 내구도 소비 그래프를 다시 그린다
➔ 다시 그리는 중에 누가 또 나가면?
➔ 다시 그리던거 마무리 하고, 또 ... 다시 그린다...
➔ 근데 참여자 중 한명이 오프라인이라면?
55. 무엇이 혼란한가?
분산된 환경에서는 객체들이 다른 프로세스에 흩어져 있다
행동의 여파가 여러 객체에 동시에 영향을 주는 경우 적용에 시간이 걸린다
그 행동이 동시에 여러 곳에서 요청이 온다면?
심지어 메모리에 올라와 있지도 않은 객체가 포함되었다면?
56. 디자인 방향의 선회
✘ 건설하는 동안 플레이어의 행동을 제한한다
✘ 게임 진행의 흐름을 끊는다
➔ 모바일 게임의 특성과 맞지 않다
앞에 붙어서 건설을 하는 시간 자체는 짧게
하지만 협동의 느낌은 나게
57. 개선된 원기옥
1명이 건설 (짧은 시간)
➔ 건축물이 완성되기를 기다림 (긴 시간)
➔ 친구가 ‘도와주기’를 하면 기다리는 시간 감소
➔ 정해진 시간이 지나면 완성
✔ 실제 앞에 붙어있어야 하는 시간이 짧다
✔ 비 동기적인 액션으로 동료가 완성 시간을 줄여줄 수 있다
58. 동시에 여러 객체를 변조하는 일은 회피하자
2개 이상의 객체에 동시에 영향을 주는 작업은 구현 비용이 비싸다
비싸게 지불하고 구현했더라도 버그 가능성이 너무 높다
유지 보수도 복잡하다
디자이너와 충분한 협의를 통해 디자인 자체를 회피하는 방향으로 선회하자
64. 실시간 알림의 필요성
• 이력 시스템은 문제를 발견하기 전까지 이용하지 않게 된다
• 문제를 발견한 이후에는 늦을 수 있다
• 내 사유짶에서 일어나는 행동에 대한 빠른 피드백을 위해
실시간으로 알림이 필요하다
65. 오프라인인 캐릭터에게 알림
• 접속 중일 때는 해당 캐릭터에게 알림을 보내면 그만
• 접속 중이 아닐 때는 어떻게 해야 할까?
• 해당 캐릭터의 DB 속 데이터를 직접 수정해야 한다
• 여러 명이 동시에 사유짶에서 활동할 경우 동시에 알림을 보낼 수도 있다
• 여러 명의 요청을 안전하게 처리할 수 있어야 한다
요청자가 서로 다른 서버에 있을 수 있음
66. 낙관적 트랜잭션
니가 알고 있던 건
최신이 아니야
동작이 단순하고 가볍다
하나의 문서만을 대상으로 할 수 있다
67. 낙관적 트랜잭션의 어려움
트랜잭션 시 수행하는 코드는 언제나 재실행이 가능해야 한다
실행은 사이드 이펙트가 없어야 한다
객체는 복잡하고 다양한 로직을 가지고 있다
객체를 대상으로는 낙관적 트랜잭션을 금지
사이드 이펙트가 누적될 수 있다
계속해서 다시 시도해야 할 수 있다
68. 객체의 소유권
• 서버에게 객체의 담당 시킬 뿐 아니라 소유권한 까지 넘긴다
• 어떤 객체에게 영향을 주고 싶으면 소유한 서버에게 문의해야 한다
• 하지만 접속 중이 아닐 때에는?
69. DB에 태스크 큐
객체마다 태스크 큐를 DB에 만든다
작업을 큐잉해 둔다
owner.queue_task(
Player.notify_estate_event, *args, **kwargs)
그 객체가 접속 중 이라면 rpc를 통해서 알려준다
접속 중이 아니었다면 접속할 때 내 큐를 확인해서 수행한다
70. 사유짶 알림
• 행동을 하는 객체는 사유짶의 주인에게 꼬박꼬박 보고를 한다
• 오프라인일 때 일어났던 일은 접속할 때 알려주고
• 온라인일 때 일어난 일은 바로 알려준다
72. 붶족 시스템
아직 시스템에서 지원을 하고 있진 않음
기반은 작업해 두었지만 더 완성도를 높여서 보여드리고 싶은 마음에
아직 공개한 적은 없음
73. 붶족과 플레이어의 관계는 서로 참조
가입이나 탈퇴는 양쪽 문서를 모두 수정해야 한다
d붶족 A
c
a
b
74. 가입과 탈퇴 시 양쪽 문서가 동시에 수정됨이 보장되지 않는다면
예상할 수 없는 문제들이 속출
d붶족 A
c
a
b
75. ACID 트랜잭션
• 안전한 트랜잭션을 위한 특징
Atomicity 부분적으로만 실행되지 않는다
Consistency 실행에 성공하면 언제나 일관된 상태로 유지된다
Isolation 수행 중 다른 트랜잭션이 끼어들 수 없다
Durability 성공한 트랜잭션은 영구히 반영된다
• 하지만 우리는 분산에 더 적한 NoSQL을 사용
• NoSQL에서는 보장하기 힘들다
76. BASE 트랜잭션
• ACID를 NoSQL에서 근사하게 보장해 주기 위한
애플리케이션 레벨의 방법
Basically Available
Soft state
Eventual consistency
• 트랜잭션에 내용을 따로 문서로 작성
• 애플리케이션 레벨에서 해당 문서를 참조하여 결과적으로 일관성을 보장함
• 애플리케이션 레벨의 처리이기 때문에 로직 자체에서 신경 써야 할 점이 많다
77. 가입과 탈퇴
가입과 탈퇴는 두개의 문서를 동시에 수정하는 작업
하지만 BASE 트랜잭션은 고민을 많이 해야하고 구현이 복잡하다
BASE 트랜잭션을 안쓰고 낙관적 트랜잭션만으로 해결할 순 없을까?
가볍지만 하나의 문서를 대상으로만 가능
78. 가입 신청
가입을 신청할 때 붶족 문서에 기록하지 말자
➔ 낙관적 트랜잭션만으로 가능
플레이어가 붶족을 가리키는 단방향 관계 형성
DB에 쿼리를 통해서 붶족은 가입하길 원하는 플레이어를 검색
79. 가입과 강제퇴출
붶족장이 가입을 승인할 땐 붶족이 플레이어를 가리키게 한다
➔ 낙관적 트랜잭션만으로 가능
붶족장이 붶족이 플레이어를 가리키지 않게 하면 강제 퇴출
하지만 이럴 경우 가입 신청한 상황과 구분이 되지 않는다!
80. 토큰의 도입
가입 신청과 수락 시에 토큰을 같이 기록한다
토큰은 유니크한 값이 발급된다
A17D3
A17D3
81. 강제 퇴출
강제로 퇴출 시에는 토큰을 만료만 시킨다
양쪽 토큰이 일치하더라도 토큰이 만료되었을 경우는 인정하지 않는다
A17D3
A17D3:만료됨
82. 4F82K
탈퇴
자진 탈퇴할 때는 조용히 나의 가리킴만 삭제
기존의 붶족 쪽 토큰은 데이터는 있지만 사실상 의미가 없다
재 가입신청을 할 때는 토큰이 바뀌어 있으므로 기존의 붶족 쪽 토큰은 무효
A17D3
83. 초대
• 초대를 보낼 때에는 붶족 쪽에서 발행하여 토큰을 초대장과 함께 보낸다
• 초대장을 보내는 순간 이미 붶족은 플레이어를 가리키고 있다
• 내가 해당 토큰으로 붶족을 가리키면 초대 수락
A17D3
A17D3
84. 낙관적 트랜잭션만으로 해결
가입 신청/ 탈퇴/ 초대 수락
➔ 플레이어 데이터만 수정
가입 수락/ 강제 탈퇴 / 초대
➔ 붶족 데이터만 수정
일반적인 로그인 세션과 다르지 않다
간단한 구조 변경을 통해 가벼운 낙관적 트랜잭션으로 해결
93. NDC16 <야생의 땅: 듀랑고>의 거친 환경에서 살아가는 동물 AI
세션에서 설명 드린 것을 참고하시면 좋을 것 같습니다.
저희는 PVE와 PVP 모두 콜로세움이라는 노드를 통해 해결니다
모든 전투와 관련된 행동들이 해당 노드에서 결정, 수행되기 때문에
전투에 관해서 만큼은 다른 서버에 있다고 하여 시간차가 발생하지
않습니다
Q
A
만약 PVP가 구현된다면, 예측 불가능한 인터랙션이 매우 많이 발생
하여 서로 다른 서버에 있는 유저들 사이에서 많은 부담이 발생할 것
같습니다. 혹시 구현 계획과 그 대책이 있나요?
여러 플레이어들과 공룡을 사냥할 때 신속한 동기화가 필요할텐데
이럴 경우 동기화의 퍼포먼스, 그리고 말씀하신 동기화로 인한 부하
가 커질텐데 그런 부분은 어떻게 해결하셨나요?Q
94. 객체는 서버에게 소유권이 이전 되어있기 때문에
다른 서버에 있는 객체 둘이 어느 목표 대상물에게 접근하려면
둘 다 목표 대상물을 소유한 서버에 rpc를 통해서
요청을 보내는 수 밖에 없습니다.
해당 서버 안에서는 객체 단위로 rpc 요청이 직렬화 되기 때문에
요청 받은 순서대로 처리하게 됩니다.
Q
A
동시에 다른 서버에 있는 유저가 같은 객체와 인터랙트하는 경우에
는 두 유저가 모두 인터랙트를 할 수 있는지? 동기화는 어떻게 처리
되는지요?
95. 병목이 생기는 부분을 분산할 예정입니다.
Q
A
서버간 동기화로 인해 패킷이 늘어나면, 물리적 네트워크 처리량이
병목이 되지 않나요? 패킷양으로 인해 물리적 네트워크 처리량에 병
목이 온다면, 어떻게 해결할 계획이신가요?
96. 인스턴트를 새로 만드는 비용은 언제나 최소한으로 맞추기 위해
노력을 했습니다. 기본적인 정보만 미리 세팅하고 상세한 정보들은
필요할 때 만들거나 읽어오도록 하였기 때문에 코스트가
크지 않습니다
Q
A
신기루그리드를 누군가 터치했을 때 인스턴스를 새로만든다면 새로
만드는 연산에 비용코스트가 크지 않나요?
97. 서버는 지리적으로는 영향력이 없기 때문에 문제가 생긴 서버에게
속한 객체가 정상적으로 동기화 되지 않는다는 문제점 정도는
있을 것이지만, 그 지역 자체에는 아무런 영향이 없습니다.
Q
A
특정 서버만이 오류가 있을 때 게임지리적으로 같은 곳에 객체가 존
재하는 다른 서버도 같이 영향을 받을텐데 이는 어떻게 해결하실 생
각인가요?
98. 아직 글로벌 서비스에 대한 준비가 완벽하지 않아서
확실하게 답변 드릴 수 있는 부분이 아닌 것 같습니다.
모바일 통신 환경에서는 기본적으로 latency가 클 수 밖에 없기 때문에
항상 높은 latenc를 가정하고 게임을 디자인하고 있습니다.
Q
A
서로 다른 지역에서 플레이 하는 사람은 해당 지역의 서버에 접속을
하나요? 그렇다면 서버간 통신 latency가 큰 경우에 어떤 문제가 생
길 수 있나요?
99. 최초로 active 상태가 되는 것은 유저의 선택 (인터랙션)에 의해서
이루어 집니다. 단순히 내부적 상태가 변하는 것은 저희도 이 때
처리하고 있습니다만, 이 세션에서 설명드린 부분은 시간에 따라
외형이 변하는 객체들 입니다. 모닥불이 활활 타고 있는 것 같지만
실제로는 꺼져있는 상태는 유저에게 혼란을 줄 수 있어 그렇게 할 수
없었습니다.
Q
A
시간에 따라 상태가 변경되는 지형물은 스케줄러에 등록해놓고 매번
처리하지말고, 최초 로 active상태가 될때 누적된 처리를 한번에 해
주면 어떤 문제가 있나요?
100. 일단 분산된 서버라는 것 자체가 원래 있던 서버에 접속할 필요가
없게 만들어야 니다. 재접속 할 때에는 원래 접속했던 서버에
접속할 확률이 낮기 때문에 언제나 관련된 정보는 DB에 저장해 두고
필요할 때마다 꺼내기 쉽게 해 놓았습니다.
Q
A
중앙서버가 없다면 비원활 네트워크 상황이 발생했을 경우, 원래 로
그인했던 게임서버에 재접속이 된다는 보장이 없을 텐데, 다른 게임
서버에 재접속 됐을 경우 예전 게임서버에 남아있는 유저의 정보와,
새로 로그인되는 유저의 정보는 어떻게 처리되는지 궁금니다.
101. 유저의 이동은 BASE 트랜잭션으로 저장하지 않고
각 소유권이 인정된 서버에서 알아서 처리하기 때문에
Eventual consistency 로 처리하지 않습니다.
그리고 각 개체는 겹쳐있는 것을 허용하기 때문에 충돌이 일어나지
않습니다.
Q
A
서로 다른 서버에 있는 두 유저가 동시에 같은 장소로 이동할 경우
Eventual Consistency로 처리 되면 위치가 충돌하지 않을까요?
102. 쉽게 답변드릴 수 없는 부분인 것 같습니다.
Q
A
듀랑고 정도의 서버 프로그래밍의 예상 개발시간 소요는
어느정도일까요
103. iOS 노티피케이션은 큐를 통해서 처리하지 않습니다.
큐에 작업을 넣을 때 필요한 경우 푸쉬(노티피케이션)을 따로
보내고 있습니다.
Q
A
오프라인인 유저가 접속해야 있던 큐를 처리하면, 오프라인인 유저
는 iOS 노티피케이션을 받을 수 없나요?
104. 누군가가 해당 지역을 처음으로 목격했을 때 로드됩니다.
해당 서버에서 그 지역에 관심 있는 객체가 하나도 존재하지 않게 되면
다시 누군가 목격할 때 까지는 메모리에서 해제니다.
Q
A
외형 캐시가 서버에 로드되는 시점이 언제인가요?
105. DB의 특정 노드에 장애가 난 상태에서 일부 DB 작업이 실패하는데
전체 서비스가 망가지진 않지만 일부 동작이 망가질 순 있습니다.
DB 자체는 persistent 니다.
Q
A
오프라인 유저에 대한 지연된 업데이트를 위해 DB큐를 둔다고 하셨
는데요. 해당 큐에 장애가 나는 경우에도 대비되어있나요?
오프라인 유저의 지연 업데이트를 위한 DB큐도 백업이 있나요? 해
당 DB큐에 장애가나면 데이터가 날아가버리지 않나요?Q
106. 게임 서버는 파이썬으로만 구성되어있습니다.
게임 서버 이외의 워커들엔 C#도 쓰고 있습니다.
Q
A
듀랑고 서버는 파이썬으로만 구성 되어 있나요?
107. 네 그렇습니다. 다만 3로 옮기는 것을 고려 중 입니다.
Q
A
파이썬 2.7에 gevent를 계속 사용하고 있나요?
108. 파이썬의 라이브러리 생태계가 아주 잘 이루어져 있기 때문이었습니다
Q
A
서버 개발 언어로 분산에 최적화된 여러 언어가 아닌(얼랭이라던가)
파이썬을 고른 이유는 무엇인가요?
109. 저희는 NoSQL인 Couchbase를 사용하고 있습니다.
Q
A
db는 awa의 rds를 쓰시나요? 다이나모를 쓰시나요 rds를 쓰신다
면 어떤 엔진을 쓰시고 그 엔진을 쓰신 이유가 있다면?