使用GWT和GAE的同步,异步和命令客户端请求

时间:2012-09-08 12:55:10

标签: java google-app-engine gwt asynchronous requestfactory

在设计我的GWT / GAE应用程序时,我很明显我的客户端(GWT)将生成三种类型的请求:

  • 同步 - “现在回答我 !我很重要,需要实时响应!!!”
  • 异步 - “当你可以时回答我;我需要在某个时候知道答案,但它真的不是那么真实。”
  • 命令 - “我不需要答案。这实际上不是一个请求,只是在服务器端做某事或处理某些事情的命令。”

我的游戏计划是为了实现我的GWT代码,以便为每个特定的服务器端请求指定(注意:我决定使用RequestFactory超出传统GWT-RPC 的原因超出了本问题的范围),请求的类型是:

  • SynchronousRequest - 同步(来自上方);发送一个命令并急切地等待一个响应,然后用它以某种方式更新客户端的状态
  • AsynchronousRequest - 异步(来自上方);提出初始请求并以某种方式 - 通过轮询或GAE Channel API,在最终收到回复时得到通知
  • CommandRequest - 命令(来自上方);提出服务器端请求并且不等待响应(即使服务器未能执行或拒绝执行该命令)

我想我对SynchronousRequest的意图不是产生完全阻止请求,但是它可能会阻止用户与屏幕的特定Widget或部分进行交互。

这里添加的踢球者是这样的:GAE在其所有前端实例(60秒)上强制执行超时。后端实例对超时,线程等具有更宽松的约束。因此,我很明显AsynchronousRequestsCommandRequests应该路由到后端实例,以便GAE超时不会成为它们的问题。

然而,如果GAE表现不佳,或者我们遇到了高峰流量,或者我的代码很简单,我必须考虑到SynchronousRequest的情况(必须要去通过超时监管的前端实例)并将超时,除非我的GAE服务器代码做了一些奇特的事情。我知道GAE API中有一个方法,我可以调用它来查看请求在其超时之前有多少毫秒;虽然它的名字现在逃脱了我,但这就是这个“花哨”代码的基础。为了这个问题,我们称之为public static long GAE.timeLeftOnRequestInMillis()

在这种情况下,我想检测到SynchronousRequest即将超时,并以某种方式将其动态转换为AsynchronousRequest,以便它不会超时。也许这意味着将AboutToTimeoutResponse发送回客户端,并强制客户端决定是重新发送为AsynchronousRequest还是仅失败。或者我们可以将SynchronousRequest转换为AsynchronousRequest并将其推送到后端实例将使用它的队列,处理它并返回响应。在实现方面我没有任何偏好,只要请求没有失败或超时,因为服务器无法足够快地处理它(因为GAE规定的规则)。

那么,这就是我实际上在这里问的问题:

  • 如何在RequestFactorySynchronousRequestAsynchronousRequest内包含CommandRequest来电,使RequestFactory调用的行为与每个调用相同旨在?换句话说,为了使部分阻塞(同步)的呼叫可以在某个时间点(非同步)通知/更新,或者可以只是发射并忘记(命令)?
  • 如何实现我的要求让SynchronousRequest绕过GAE的60秒超时并仍然可以不失败地处理?

请注意:通过将内容重新路由到后端实例可以轻松避免超时问题,但后端不能/无法扩展。我也需要这里的可扩展性(这主要是我首先在GAE上的原因!) - 所以我需要一个处理可扩展前端实例及其超时的解决方案。提前谢谢!

1 个答案:

答案 0 :(得分:0)

如果您希望GAE执行的计算花费的时间超过60秒,则不要等待在发送响应之前计算结果。根据你的问题定义,没有办法解决这个问题。相反,客户端应提交工作订单,并在结果准备好后等待服务器发出通知。请求将包含工作订单,可能如下所示:

class ComputeDigitsOfPiWorkOrder {
  // parameters for the computation
  int numberOfDigitsToCompute;

  // Used by the GAE app to contact the requester when results are ready.
  ClientId clientId;
}

这样,您的GAE应用程序可以在保存工单(例如在任务队列中)后立即响应,并且不必等到它在响应之前实际完成计算十亿个数字的pi。然后,您的GWT客户端将使用Channel API等待结果。

为了给某些工作单提供更高的优先级,您可以使用多个任务队列。如果您希望任务队列工作自动扩展,您将需要使用推送队列。使用推送队列实现优先级有点棘手,但您可以configure high priority queues获得更快的Feed率。

您可以使用其他一些通知解决方案替换Channel API,但这可能是最直接的。