这是适合我们的MMORPG手机游戏的架构吗?


14

这些天,我正在尝试为公司设计一款新的MMORPG手机游戏的体系结构。该游戏类似于黑手党战争,iMobsters或风险。基本思想是准备一支军队与您的对手(在线用户)作战。

尽管我以前曾从事过多个移动应用程序的工作,但这对我来说却是新事物。经过大量的努力,我提出了一个架构,该架构借助高级流程图进行了说明:

高级流程图

我们决定采用客户端-服务器模型。服务器上将有一个集中式数据库。每个客户端将拥有自己的本地数据库,该本地数据库将与服务器保持同步。该数据库用作存储不经常更改的内容(例如地图,产品,库存等)的缓存。

使用此模型后,我不确定如何解决以下问题:

  • 同步服务器和客户端数据库的最佳方法是什么?
  • 在将事件更新到服务器之前,是否应该将事件保存到本地数据库?如果应用由于某种原因终止,然后将更改保存到集中式数据库,该怎么办?
  • 简单的HTTP请求是否可以达到同步目的?
  • 如何知道当前登录的用户?(一种方法是让客户端每隔x分钟继续向服务器发送一个请求,以通知该请求处于活动状态。否则,认为客户端处于非活动状态)。
  • 客户端验证足够吗?如果没有,如果服务器未验证某些内容,如何还原操作?

我不确定这是否是一个有效的解决方案,以及它将如何扩展。如果已经在此类应用程序上工作的人们能够分享他们的经验,这可能有助于我提出更好的建议,我将不胜感激。提前致谢。

附加信息:

客户端是在称为果酱的C ++游戏引擎中实现的。这是一个跨平台的游戏引擎,这意味着您可以在所有主要的移动操作系统上运行您的应用程序。我们当然可以实现线程化,这在我的流程图中也有说明。我打算将MySQL用于服务器,将SQLite用于客户端。

这不是回合制游戏,因此与其他玩家的互动不多。服务器将提供在线玩家列表,您可以通过单击“战斗”按钮与他们进行战斗,并在播放一些动画后宣布结果。

对于数据库同步,我想到了两种解决方案:

  1. 存储每个记录的时间戳。还应跟踪本地数据库的最新更新时间。同步时,仅选择时间戳较大的行并将其发送到本地数据库。为已删除的行保留一个isDeleted标志,以便每个删除行为都只是一个更新。但是我对性能有严重的怀疑,因为对于每个同步请求,我们都必须扫描整个数据库并查找更新的行。
  2. 另一种技术可能是保留针对用户进行的每次插入或更新的日志。当客户端应用程序要求同步时,请转到该表并找出已更新或插入了该表的哪些行。这些行成功传输到客户端后,请删除此日志。但是我想到了如果用户使用其他设备会发生什么。根据日志表,已为该用户传输了所有更新,但实际上是在另一台设备上完成的。因此,我们可能还必须跟踪设备。实施此技术比较耗时,但不确定是否会执行第一个。

2
我将对MsSQL进行评估,并进行改进-我不确定MySQL在复制方面提供了什么,但是MsSQL 2008 R2为您提供了LOAD的复制(5-6)技术供您选择。只是想一想,而不是讨厌MySQL或其他任何东西,但是Microsoft确实擅长集群。
乔纳森·迪金森

1
@乔纳森·迪金森(Jonathan Dickinson):有MySQL群集:P
郊狼

1
还要看一下PostgreSQL-版本9具有复制技术,PostgreSQL在处理重负载方面一直享有良好的长期声誉,许多开发人员似乎都是优化坚果,而最好的是它是开源的并且对于所有用途都是完全免费的(包括商业广告)。
兰道夫·理查森

问题是我们不能在客户端和服务器端使用相同的数据库。我认为最适合客户端的数据库将是SQLite,因此它不会消耗大量资源,因为应用程序将在移动设备上运行。虽然从事服务器工作的人员仅了解MySQL,所以这就是我们选择它的原因。我也听说大多数MMO游戏都使用MySQL数据库。
umair 2011年

1
@umair:客户端可以是SQLite(例如在iPhone上已经可用)。但是,您可以选择只将所需的相关数据存储在文件中(无论SQLite做什么),而不必理会客户端DB,就像使用Javascript应用程序一样。
郊狼

Answers:


15

如果它不是“实时”游戏,并且玩家不需要看到其他玩家在游戏场景中的动作的即时结果,那么使用HTTP请求就可以了。但是请记住HTTP的开销。

也就是说,使用HTTP不会避免您精心设计通信协议。但是,如果您同时负责服务器和客户端,那么您会很幸运,因为您可以在需要时调整协议。

要在主数据库和客户端数据库之间进行同步,可以使用您可以访问的任何传输协议(HTTP或其他协议)。重要的部分是同步背后的逻辑。对于直接的方法,只需从服务器池中收集自客户端数据库中上一个时间戳以来客户端所需的所有最新更改。将其应用到客户端数据库并继续。如果您在客户端有更多更改,请上传仍然有用的内容,否则将其丢弃。

有些游戏甚至不使用本地数据库,它们只是通过在需要时从服务器中汇集相关信息来跟踪状态。

如果丢失本地事件是不可接受的,那么可以,您应该拥有本地存储,并尽可能多地保存到该存储中。您可以在每个网络发送之前尝试这样做。

为了检查活跃用户,我们曾经在成功的游戏中每20秒使用ping命令HTTP ...当服务器过载时,该值立即上升:(服务器团队没有考虑成功。所以我告诉您添加通信协议中的消息或某种特殊的标头,可让您重新配置客户端(用于ping频率负载平衡和其他与通信相关的值)。

如果您不介意骗子,黑客和其他自动脚本攻击您的游戏,则客户端验证就足够了。服务器可以简单地拒绝您的操作并发送包含一些详细信息的错误消息。您可以通过回滚本地更改或不将其应用于本地存储来处理该错误消息,如果您可以等到服务器响应以实际保存更改之后,则可以解决该错误消息。

我们在游戏中使用了命令模式,以允许简单有效地回滚失败或无效的用户操作。命令在本地播放后发送到对等方或转换为服务器消息,然后应用到对等方或在服务器上检查,如果出现问题,则不播放命令,并且游戏场景会通过通知返回初始状态。

使用HTTP并不是一个坏主意,因为稍后,它将允许您非常轻松地与Flash或HTML5客户端集成,它非常灵活,可以使用任何类型的服务器脚本语言,并且借助基本的负载平衡技术,以后无需花费太多精力即可添加更多服务器扩展您的后端。

您有很多工作要做,但这是一项有趣的工作...尽情享受吧!


3
为“ HTML可能足够好” +1,因为它可能是:)。
乔纳森·狄金森

1
@土狼:感谢您抽出宝贵的时间并提供如此详细的答案。真的很像您的HTTP思想,即为其他客户端提供支持。
umair 2011年

1
愿力量与您同在:)
郊狼

5

同步服务器和客户端数据库的最佳方法是什么?

最简单的方法是将数据库实现为可以传输的单个文件。如果您想尝试比较数据库之间的差异,那将是一个痛苦的世界,我是根据经验讲的。

请注意,您的服务器不得信任客户端基于该本地数据库做出的决定,因为客户端可以更改它。它必须纯粹是为了呈现细节而存在。

在将事件更新到服务器之前,是否应该将事件保存到本地数据库?

否。如果服务器认为该事件从未发生怎么办?无论如何,客户端都不应该对事件做出决定,因为客户端不能被信任。

我注意到您还以两种方式谈论本地数据库:一种是用于“不经常更改的事物”,另一种是用于事件的。由于上述原因,它们实际上不应该在同一个数据库中-您不想开始尝试合并或区分数据库中的各个数据行。例如,当客户端引用您决定从服务器中删除的项目时,引用完整性就会成为问题。或者,如果客户端更改了一行而服务器更改了一行,那么哪个更改优先,为什么?

简单的HTTP请求是否可以达到同步目的?

是的,但前提是它们很少出现或很小。HTTP带宽效率不高,因此请记住这一点。

如何知道当前登录的用户?(一种方法是让客户端每隔x分钟继续向服务器发送一个请求,以通知该请求处于活动状态。否则,认为客户端处于非活动状态)。

如果您使用HTTP之类的瞬态协议,那么这是一个合理的想法。当服务器收到来自客户端的消息时,您可以更新该客户端的“最后见”时间。

客户端验证足够吗?如果没有,如果服务器未验证某些内容,如何还原操作?

一点都不。客户在敌人的手中。如何还原动作完全取决于您认为动作是什么以及其可能产生的影响。最简单的方法是在服务器响应以允许该操作之前根本不执行该操作。稍微棘手的方法是确保每个操作都具有回滚功能以撤消该操作,并在客户端上缓存所有未确认的操作。服务器确认它们后,将其从缓存中删除。如果某个动作被拒绝,则以相反的顺序回滚每个动作,直到并包括被拒绝的动作。


1
你钉了 同步数据库+1是对的,客户端永远不要自己更改数据库...只需调用在服务器上运行的函数,并使用游戏的逻辑更新数据库,然后检索结果即可。
郊狼

@Kylotan:感谢您指出我模型中的流程
-umair

@Kylotan:“最简单的方法是将数据库实现为可以传输的单个文件。如果您尝试比较数据库之间的差异,那将是一个痛苦的世界,根据经验我可以说。” 这意味着每次启动应用程序时都会下载所有数据。有些事情不会经常更改,因此每次都不能下载。这也将大大增加应用程序的启动时间。有什么想法吗?
umair

如果数据很小,那么问​​题就消失了。如果您的静态数据集中式数据库很大,我会感到惊讶。但是无论如何,如果将静态数据分成较小的部分,则只需要发送自上次以来已更改的数据。当然,如果您愿意在每一行中保留修改时间,则可以逐行执行此操作。通常,我更喜欢在关系数据库之外使用静态数据,以便我可以轻松地覆盖它。
Kylotan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.