GAE/GWT 服务器端数据不一致/实例之间不持久



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

我知道这可能与appspot如何成为云服务有关,并且它可以随时生成和使用我的servlet的新实例,并且现有数据不会在实例之间持久化。

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

我已经看了一下数据存储API,它似乎是像存储一样的数据库,我猜这对于我需要的东西来说太慢了。此外,Memcache可以随时刷新,因此没有用。

我在这里错过了什么?

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

  1. 当您拥有分布式 Servlet 环境(如 GAE(时,您不能向一个实例发出请求,将数据保存到内存中并期望数据在其他实例上可用。对于 GAE 和具有多个服务器的任何其他 servlet 环境都是如此。

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

    在 GAE 上,还有第三种选择可以拥有半持久化的共享数据:后端。这些是始终在线的实例,您可以在其中控制启动/关闭。

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

简短回答:您没有将游戏设计为在 App Engine 上运行。

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

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

如果要使用单个服务器,

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

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

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

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

如果是这样,那么我同意彼得·克内戈关于内存缓存等的回答。

如果没有,那么您可以通过选择其他托管选项(GAE 除外(来解决问题。特别是允许您仅使用单个实例的实例。然后,您确实可以简单地管理服务器内存中的所有游戏数据,就像我所理解的那样,到目前为止您一直在这样做。

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

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

请注意,上述解决方案涉及一些摆弄,我不太了解您的需求,无法提出强烈建议。对于您要做的事情,可能会有更简单、更好的解决方案。特别是,查看针对高度时间关键型实时多人游戏优化的非基于云的托管选项和服务器架构。

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

最新更新