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

时间:2012-05-16 14:07:57

标签: java google-app-engine gwt persistence

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

据我所知,这可能与appspot是一个多云的服务有关,并且它可以在任何时候产生并使用我的servlet的新实例,并且现有数据不会在实例之间持久存在。

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

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

我在这里缺少什么?

3 个答案:

答案 0 :(得分:3)

这里有两个问题:在请求之间保留数据并从客户端轮询数据。

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

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

    在GAE上,还有第三种方法可以使用半持久共享数据:backends。这些是永远在线的实例,您可以控制启动/关闭。

  2. 数据轮询:如果有多个客户端等待更新,最好不要使用轮询。轮询将产生大量不必要的请求(数据在服务器上没有变化),并且仍然会有最小的延迟(因为您以某个间隔轮询)。而不是轮询你使用推送Channel API。甚至还有GWT库:gwt-gae-channelgwt-channel-api

答案 1 :(得分:1)

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

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

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

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

答案 2 :(得分:0)

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

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

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

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

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

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

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

请注意,上述解决方案涉及一些小问题,我不太了解您的需求以提出强烈建议。对于您正在尝试的内容,可能会有更简单,更好的解决方案。特别是,请查看针对高度时间关键的实时多人游戏进行优化的非基于云的托管选项和服务器架构。

希望这有帮助!让我们发布您的进度。