이것이 MMORPG 모바일 게임에 적합한 아키텍처입니까?


14

요즘 저는 회사를위한 새로운 MMORPG 모바일 게임의 아키텍처를 설계하려고합니다. 이 게임은 Mafia Wars, iMobsters 또는 RISK와 유사합니다. 기본 아이디어는 상대방 (온라인 사용자)과 싸울 군대를 준비하는 것입니다.

이전에 여러 모바일 앱에서 작업 한 적이 있지만 이것은 새로운 것입니다. 많은 어려움을 겪은 후, 나는 고급 흐름도를 통해 설명 된 아키텍처를 생각해 냈습니다.

높은 수준의 흐름도

우리는 클라이언트-서버 모델로 가기로 결정했습니다. 서버에 중앙 집중식 데이터베이스가 있습니다. 각 클라이언트에는 자체 로컬 데이터베이스가 있으며 서버와 동기화 상태를 유지합니다. 이 데이터베이스는 자주 변경되지 않는 사항 (예 :지도, 제품, 인벤토리 등)을 저장하기위한 캐시 역할을합니다.

이 모델을 사용하면 다음 문제를 해결하는 방법을 잘 모르겠습니다.

  • 서버와 클라이언트 데이터베이스를 동기화하는 가장 좋은 방법은 무엇입니까?
  • 이벤트를 서버로 업데이트하기 전에 로컬 DB에 저장해야합니까? 중앙 DB에 변경 사항을 저장하기 전에 어떤 이유로 앱이 종료되면 어떻게됩니까?
  • 간단한 HTTP 요청이 동기화 목적에 도움이됩니까?
  • 현재 로그인 한 사용자를 확인하는 방법 (한 가지 방법은 클라이언트가 x 분마다 서버에 요청을 계속 보내서 활성화되었음을 알리는 것입니다. 그렇지 않으면 클라이언트가 비활성화 된 것으로 간주합니다).
  • 클라이언트 측 유효성 검사가 충분합니까? 그렇지 않은 경우 서버가 무언가를 검증하지 않으면 조치를 되 돌리는 방법은 무엇입니까?

이것이 효율적인 솔루션인지 어떻게 확장되는지 확실하지 않습니다. 이미 그러한 앱에서 일한 사람들이 자신의 경험을 공유하여 더 나은 무언가를 생각 해낼 수 있다면 정말 감사하겠습니다. 미리 감사드립니다.

추가 정보:

클라이언트 쪽은 marmalade라는 C ++ 게임 엔진에서 구현됩니다. 크로스 플랫폼 게임 엔진으로 모든 주요 모바일 OS에서 앱을 실행할 수 있습니다. 우리는 확실히 스레딩을 달성 할 수 있으며 이는 흐름도에 설명되어 있습니다. 서버에는 MySQL을, 클라이언트에는 SQLite를 사용할 계획입니다.

이것은 턴 기반 게임이 아니므로 다른 플레이어와의 상호 작용이 많지 않습니다. 서버는 온라인 플레이어 목록을 제공하며 전투 버튼을 클릭하여 전투를 벌일 수 있으며 일부 애니메이션 후에 결과가 발표됩니다.

데이터베이스 동기화를 위해 두 가지 솔루션을 염두에 두십시오.

  1. 각 레코드의 타임 스탬프를 저장하십시오. 또한 로컬 DB가 마지막으로 업데이트 된시기를 추적하십시오. 동기화 할 때 타임 스탬프가 더 큰 행만 선택하고 로컬 DB로 보냅니다. 삭제 된 행에 대해 isDeleted 플래그를 유지하면 모든 삭제가 단순히 업데이트로 작동합니다. 그러나 모든 동기화 요청에 대해 전체 DB를 스캔하고 업데이트 된 행을 찾아야하는 성능에 대해 심각한 의문이 있습니다.
  2. 다른 기술은 사용자에 대해 발생하는 각 삽입 또는 업데이트에 대한 로그를 유지하는 것입니다. 클라이언트 앱이 동기화를 요청하면이 테이블로 이동하여 업데이트 또는 삽입 된 테이블의 행을 찾으십시오. 이 행이 클라이언트로 성공적으로 전송되면이 로그를 제거하십시오. 그러나 사용자가 다른 장치를 사용하면 어떻게 될지 생각합니다. 로그 표에 따르면 해당 사용자에 대한 모든 업데이트가 전송되었지만 실제로는 다른 장치에서 수행되었습니다. 따라서 장치도 추적해야 할 수도 있습니다. 이 기술을 구현하는 데 시간이 오래 걸리지 만 첫 번째 기술을 수행하는지 확실하지 않습니다.

2
나는 MsSQL의 평가를 얻고 그것으로 바이올린을 사용할 것이다. MySQL이 복제 측면에서 무엇을 제공하는지 잘 모르겠지만 MsSQL 2008 R2는 선택할 수있는 LOAD of replication (5-6) 기법을 제공한다. MySQL이나 다른 것을 싫어하지는 않지만 Microsoft는 실제로 클러스터링에 능숙합니다.
Jonathan Dickinson

1
@Jonathan Dickinson : MySQL 클러스터가 있습니다 : P
Coyote

1
PostgreSQL을 살펴보십시오. 버전 9에는 복제 기술이 있으며 PostgreSQL은 많은 양의 부하를 실제로 잘 처리하는 데 탁월한 명성을 가지고 있으며 많은 개발자가 최적화 너트 인 것 같습니다. (상업용 포함).
Randolf Richardson 18

문제는 클라이언트와 서버 측에서 동일한 데이터베이스를 사용할 수 없다는 것입니다. 클라이언트에 가장 적합한 DB는 SQLite이므로 모바일 장치에서 앱이 실행될 때 많은 리소스를 소비하지 않습니다. 서버 부분에서 일하는 사람은 MySQL 만 알고 있기 때문에이를 선택했습니다. 또한 대부분의 MMO 게임은 MySQL 데이터베이스를 사용한다고 들었습니다.
umair

1
@umair : 클라이언트 측은 SQLite 일 수 있습니다 (예 : iPhone에서는 이미 사용 가능). 그러나 필요한 관련 데이터 만 파일에 저장하고 (어쨌든 SQLite가하는 일) Javascript 앱에서와 마찬가지로 모든 종류의 클라이언트 쪽 DB를 방해하지 않도록 선택할 수 있습니다.
코요테

답변:


15

플레이어가 게임 장면에서 다른 플레이어의 행동의 즉각적인 결과를 볼 필요가 없다는 의미에서 "실시간"게임이 아니라면 HTTP 요청으로 괜찮을 것입니다. 그러나 HTTP의 오버 헤드를 명심하십시오.

HTTP를 사용한다고해서 통신 프로토콜을주의해서 디자인하는 데 도움이되지는 않습니다. 그러나 서버와 클라이언트 측을 모두 담당하는 경우 필요할 때 프로토콜을 조정할 수 있으므로 운이 좋습니다.

마스터 DB와 클라이언트 DB간에 동기화하기 위해 액세스 할 수있는 전송 프로토콜, HTTP 또는 기타 프로토콜을 사용할 수 있습니다. 중요한 부분은 동기화의 논리입니다. 간단한 접근 방식을 위해서는 클라이언트 DB의 마지막 타임 스탬프 이후 클라이언트가 필요로하는 모든 최신 변경 사항을 서버에서 간단히 풀링하십시오. 클라이언트 DB에 적용하고 함께 진행하십시오. 클라이언트 측에서 더 많은 변경 사항이있는 경우 여전히 관련이 있으면 업로드하고, 그렇지 않으면 버립니다.

일부 게임은 로컬 DB를 사용하지 않고 필요할 때 서버에서 관련 정보를 풀링하여 상태를 추적합니다.

로컬 이벤트를 잃어 버릴 수 없으면 예, 로컬 스토리지를 보유하고 가능한 한 자주 해당 스토리지에 저장해야합니다. 각 네트워크 전송 전에이를 시도 할 수 있습니다.

성공적인 게임에서 20 초마다 HTTP로 핑을 사용했던 활동적인 사용자를 확인하기 위해 ... 서버가 오버로드되면이 값이 즉시 증가했습니다. (서버 팀은 성공에 대해 생각하지 않았습니다. 핑 주파수로드 밸런싱 및 기타 통신 관련 값에 대해 클라이언트를 재구성 할 수있는 통신 프로토콜의 메시지 또는 특수 헤더.

사기꾼, 해커 및 기타 자동 스크립트가 게임을 공격하는 데 신경 쓰지 않으면 클라이언트 측 유효성 검사로 충분합니다. 서버는 단순히 작업을 거부하고 세부 정보가 포함 된 오류 메시지를 보낼 수 있습니다. 서버가 실제로 변경 사항을 저장하기 위해 응답 할 때까지 대기 할 수있는 경우 로컬 변경 사항을 롤백하거나 로컬 스토리지에 적용하지 않음으로써 해당 오류 메시지를 처리합니다.

게임에서 명령 패턴을 사용하여 실패하거나 유효하지 않은 사용자 동작을 간단하고 효율적으로 롤백 할 수있었습니다. 명령은 로컬로 피어에게 전송되거나 서버 메시지로 변환 된 다음 피어에 적용되거나 서버에서 확인되었습니다. 문제가 발생하면 명령이 재생되지 않고 게임 장면이 알림과 함께 초기 상태로 돌아갔습니다.

HTTP를 사용하는 것은 나쁘지 않습니다. 나중에 Flash 또는 HTML5 클라이언트와 매우 쉽게 통합 할 수 있습니다. 유연하고 모든 유형의 서버 스크립팅 언어를 사용할 수 있으며 기본적인로드 밸런싱 기술을 사용하면 나중에 많은 노력없이 더 많은 서버를 추가 할 수 있습니다 백엔드를 확장하십시오.

할 일이 많지만 재밌는 직업입니다 ... 즐기세요!


3
'HTML 아마도 충분할 것입니다'는 +1 일 것입니다. :)
Jonathan Dickinson

1
@Coyote : 시간을내어 자세한 답변을 해주셔서 감사합니다. 다른 클라이언트에 대한 지원을 제공하려는 HTTP 아이디어와 정말 같습니다.
umair

1
힘이 당신과 함께 할 수 있습니다 :)
코요테

5

서버와 클라이언트 데이터베이스를 동기화하는 가장 좋은 방법은 무엇입니까?

가장 쉬운 방법은 데이터베이스를 전송 가능한 단일 파일로 구현하는 것입니다. 데이터베이스 간의 차이점을 비교하려고하면 고통의 세계이며 경험에서 말합니다.

서버는 클라이언트가 해당 로컬 데이터베이스를 기반으로 한 결정을 신뢰해서는 안됩니다. 클라이언트는이를 변경할 수 있기 때문입니다. 프리젠 테이션 세부 사항을 위해 순수하게 존재해야합니다.

이벤트를 서버로 업데이트하기 전에 로컬 DB에 저장해야합니까?

서버가 이벤트가 발생하지 않았다고 판단하면 어떻게됩니까? 클라이언트는 신뢰할 수 없기 때문에 이벤트에 대해 결정을 내리지 않아야합니다.

로컬 DB에 대해서도 두 가지 방식으로 이야기하고 있습니다. 하나는 "자주 변경되지 않는 것"과 두 가지 방법입니다. 위와 같은 이유로 이들은 실제로 동일한 데이터베이스에 있어서는 안됩니다. 데이터베이스의 개별 데이터 행을 병합하거나 분산 시키려고하지 않습니다. 예를 들어, 클라이언트가 서버에서 제거하기로 결정한 항목에 대한 참조가 클라이언트에 있으면 참조 무결성이 문제가됩니다. 또는 클라이언트가 행을 변경하고 서버가 행을 변경하면 어떤 변경이 우선하며 그 이유는 무엇입니까?

간단한 HTTP 요청이 동기화 목적에 도움이됩니까?

그렇습니다. 매우 드물거나 작습니다. HTTP는 대역폭 효율적이지 않으므로 명심하십시오.

현재 로그인 한 사용자를 확인하는 방법 (한 가지 방법은 클라이언트가 x 분마다 서버에 요청을 계속 보내서 활성화되었음을 알리는 것입니다. 그렇지 않으면 클라이언트가 비활성화 된 것으로 간주합니다).

HTTP와 같은 임시 프로토콜을 사용하는 경우 이는 합리적인 아이디어입니다. 서버가 클라이언트로부터 메시지를 받으면 해당 클라이언트에 대한 '최근에 본'시간을 업데이트 할 수 있습니다.

클라이언트 측 유효성 검사가 충분합니까? 그렇지 않은 경우 서버가 무언가를 검증하지 않으면 조치를 되 돌리는 방법은 무엇입니까?

아뇨, 전혀 아닙니다. 클라이언트는 적의 손에 달려 있습니다. 행동을 되 돌리는 방법은 행동으로 간주하는 것과 행동에 미치는 영향에 전적으로 달려 있습니다. 가장 쉬운 경로는 서버가 응답하도록 응답 할 때까지 작업을 전혀 구현하지 않는 것입니다. 약간 까다로운 경로는 모든 작업에 작업을 실행 취소하고 승인되지 않은 모든 작업을 클라이언트에 캐시 할 수있는 롤백 기능이 있는지 확인하는 것입니다. 서버가 승인하면 캐시에서 삭제하십시오. 조치가 거부되면 거부 된 조치를 포함하여 각 조치를 역순으로 롤백하십시오.


1
니가 끝냈어. 당신은 DB 동기화 +1에 대해 맞습니다 클라이언트는 절대로 DB를 스스로 변경해서는 안됩니다 ... 서버에서 실행되는 함수를 호출하고 게임의 논리를 사용하여 DB를 업데이트 한 다음 결과를 검색하십시오.
코요테

@Kylotan : 지적 주셔서 감사합니다 내 모델에서 흘러
UMAIR

@Kylotan : "가장 쉬운 방법은 전송할 수있는 단일 파일로 데이터베이스를 구현하는 것입니다. 데이터베이스 간의 차이점을 비교하려고하면 고통의 세계입니다. 그리고 저는 경험을 통해 말합니다." 즉, 응용 프로그램을 시작할 때마다 모든 데이터가 다운로드됩니다. 자주 변경되지 않는 사항이 있으므로 매번 다운로드하지 못할 수도 있습니다. 또한 앱의 시작 시간이 상당히 늘어납니다. 이견있는 사람?
umair

데이터가 작 으면 문제가 해결됩니다. 정적 데이터의 중앙 집중식 데이터베이스가 매우 큰 경우 놀랍습니다. 어쨌든 정적 데이터를 더 작은 부분으로 나누면 마지막 시간 이후 변경된 내용 만 보내면됩니다. 물론, 각 행에서 수정 시간을 기꺼이 유지하려는 경우 행 단위로이 작업을 수행 할 수 있습니다. 일반적으로 관계형 DB 외부에 정적 데이터를 사용하여 쉽게 덮어 쓸 수 있습니다.
Kylotan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.