【问题标题】:GAE/GWT server side data inconsistent / not persisting between instancesGAE/GWT 服务器端数据不一致/实例之间不持久
【发布时间】:2012-05-16 14:07:57
【问题描述】:

我正在使用 GWT/Java 在 GAE 上编写游戏应用程序,并且遇到了服务器端持久数据的问题。 玩家使用 RPC 轮询活动游戏和游戏状态,所有这些都存储在服务器上。有时客户端轮询无法找到我知道应该存在的游戏实例。这只发生在我部署到 google apppot 时,本地一切都很好。

我知道这可能与 apppot 是一项云服务有关,它可以在任何时候生成和使用我的 servlet 的新实例,并且现有数据不会在实例之间保留。

单个游戏只持续一两分钟,并且数据会迅速变化(每秒多次),那么确保对不同实例的 RPC 调用将使用相同的服务器端数据的最佳方法是什么?

我查看了 DataStore API,它似乎是数据库之类的存储,我猜这对于我需要的东西来说太慢了。 Memcache 也可以在任何时候刷新,所以没用。

我在这里错过了什么?

【问题讨论】:

    标签: java google-app-engine gwt persistence


    【解决方案1】:

    这里有两个问题:请求之间的持久数据和来自客户端的轮询数据。

    1. 当您拥有分布式 servlet 环境(例如 GAE)时,您无法向一个实例发出请求,将数据保存到内存并期望数据在其他实例上可用。这适用于 GAE 和任何其他有多个服务器的 servlet 环境。

      因此,您需要将数据保存到某个共享存储中:Datastore 成本高、持久、可靠且速度慢。 Memcache 快速、免费,但不可靠。通常我们使用两者的组合。一些库甚至透明地结合了两者:NDBobjectify

      在 GAE 上,还有第三个选项可以拥有半持久化的共享数据:backends。这些是永远在线的实例,您可以在其中控制启动/关闭。

    2. 数据轮询:如果您有多个客户端等待更新,最好不要使用轮询。轮询会发出很多不必要的请求(服务器上的数据没有改变),并且仍然会有最小的延迟(因为您每隔一段时间就会进行轮询)。您可以通过Channel API 使用推送而不是轮询。甚至还有 GWT 库:gwt-gae-channelgwt-channel-api

    【讨论】:

      【解决方案2】:

      简答:您没有设计游戏来在 App Engine 上运行。

      您听起来好像已经回答了自己的问题。您了解数据不会跨实例持久化。在服务器端持久化数据的两种机制是 memcache 和数据存储,但您也了解它们的局限性。你需要围绕这个来构建你的游戏。

      如果您没有使用 memcache 或数据存储,您是如何持久化数据的(我最好的猜测是您实际上并没有持久化它)。从模糊的细节来看,您尚未将游戏架构成能够跨多个实例运行,这对于在 App Engine 上运行的任何应用程序都是必不可少的。这是一个基本的设计原则,你不知道任何 HTTP 请求会命中哪个实例。您必须重新架构才能使用数据存储区 + 内存缓存。

      如果您想使用单台服务器,您可以使用后端,它的行为类似于一直存在的单台服务器(如果您将其限制为一个实例)。坦率地说,由于成本的原因,如果你走这条路,你最好选择亚马逊或 Rackspace。您还必须自己处理扩展问题 - 即,如果游戏在特定服务器实例上运行,您需要构建一种方式,以便玩游戏时始终命中该实例。

      【讨论】:

      • 你说我没有持久化数据是正确的,问题本质上是如何根据我的要求在多个实例中持久化它,如果可能的话。
      • 到目前为止您提供的信息太模糊,我无法给您更多真实的反馈。我不会在应用引擎之上构建实时 FPS 或 RTS 游戏,这似乎是错误的架构。您将不得不使用数据存储和内存缓存来提高性能。写入频率和一致性模型的限制会使它变得非常困难,而且如果您遇到严重的内存缓存故障并且您必须运行到数据存储区,您会遇到性能问题。我会为实时游戏推荐另一种服务器架构。
      • 如果您真的想使用 App Engine 并且愿意跳出框框思考,您可能会将您的游戏设计为点对点系统,并且仅将应用引擎用于存储分数等内容,或者将您的游戏重新设计为对服务器端性能要求较少的回合制游戏。
      【解决方案3】:

      请记住,您可以在没有 GAE 的情况下部署 GWT 应用程序,请参阅以下说明:

      https://developers.google.com/web-toolkit/doc/latest/DevGuideServerCommunication#DevGuideRPCDeployment

      您可能想问自己:您的应用程序是否需要多个服务器实例或 GAE 特定功能?

      如果是这样,那么我同意 Peter Knego 关于 memcache 等的回复。

      如果没有,那么您可以通过选择不同的托管选项(GAE 除外)来解决您的问题。特别是让您只使用一个实例的方法。然后,您确实可以简单地管理服务器内存中的所有游戏数据,就像我了解您迄今为止所做的那样。

      如果此解决方案适合您的目的,那么您需要做的就是找到合适的托管服务提供商。这很可能是一种基于云的 PaaS 产品,前提是它们允许您对服务器实例的数量设置一个限制(与 GAE 不同),并且它可以低至一个。例如,据我所知,Heroku (当前) 可以让你这样做,而且显然它适用于 GWT 应用程序,根据这个线程:

      https://stackoverflow.com/a/8583493/2237986

      请注意,上述解决方案有点麻烦,我不知道您的需求足以提出强烈建议。对于您正在尝试做的事情,可能会有更简单和更好的解决方案。特别是,请查看针对时间要求高的实时多人游戏进行了优化的非基于云的托管选项和服务器架构。

      希望这会有所帮助!让我们随时了解您的进度。

      【讨论】:

        猜你喜欢
        • 2022-10-12
        • 1970-01-01
        • 2016-05-03
        • 1970-01-01
        • 1970-01-01
        • 2018-03-03
        • 1970-01-01
        • 1970-01-01
        • 2022-11-27
        相关资源
        最近更新 更多