在设计我的GWT / GAE应用程序时,我很明显我的客户端(GWT)将生成三种类型的请求:
我的游戏计划是为了实现我的GWT代码,以便为每个特定的服务器端请求指定(注意:我决定使用RequestFactory
超出传统GWT-RPC 的原因超出了本问题的范围),请求的类型是:
SynchronousRequest
- 同步(来自上方);发送一个命令并急切地等待一个响应,然后用它以某种方式更新客户端的状态AsynchronousRequest
- 异步(来自上方);提出初始请求并以某种方式 - 通过轮询或GAE Channel API,在最终收到回复时得到通知CommandRequest
- 命令(来自上方);提出服务器端请求并且不等待响应(即使服务器未能执行或拒绝执行该命令)我想我对SynchronousRequest
的意图不是产生完全阻止请求,但是它可能会阻止用户与屏幕的特定Widget
或部分进行交互。
这里添加的踢球者是这样的:GAE在其所有前端实例(60秒)上强制执行超时。后端实例对超时,线程等具有更宽松的约束。因此,我很明显AsynchronousRequests
和CommandRequests
应该路由到后端实例,以便GAE超时不会成为它们的问题。
然而,如果GAE表现不佳,或者我们遇到了高峰流量,或者我的代码很简单,我必须考虑到SynchronousRequest
的情况(必须要去通过超时监管的前端实例)并将超时,除非我的GAE服务器代码做了一些奇特的事情。我知道GAE API中有一个方法,我可以调用它来查看请求在其超时之前有多少毫秒;虽然它的名字现在逃脱了我,但这就是这个“花哨”代码的基础。为了这个问题,我们称之为public static long GAE.timeLeftOnRequestInMillis()
。
在这种情况下,我想检测到SynchronousRequest
即将超时,并以某种方式将其动态转换为AsynchronousRequest
,以便它不会超时。也许这意味着将AboutToTimeoutResponse
发送回客户端,并强制客户端决定是重新发送为AsynchronousRequest
还是仅失败。或者我们可以将SynchronousRequest
转换为AsynchronousRequest
并将其推送到后端实例将使用它的队列,处理它并返回响应。在实现方面我没有任何偏好,只要请求没有失败或超时,因为服务器无法足够快地处理它(因为GAE规定的规则)。
那么,这就是我实际上在这里问的问题:
RequestFactory
,SynchronousRequest
和AsynchronousRequest
内包含CommandRequest
来电,使RequestFactory
调用的行为与每个调用相同旨在?换句话说,为了使部分阻塞(同步)的呼叫可以在某个时间点(非同步)通知/更新,或者可以只是发射并忘记(命令)?SynchronousRequest
绕过GAE的60秒超时并仍然可以不失败地处理?请注意:通过将内容重新路由到后端实例可以轻松避免超时问题,但后端不能/无法扩展。我也需要这里的可扩展性(这主要是我首先在GAE上的原因!) - 所以我需要一个处理可扩展前端实例及其超时的解决方案。提前谢谢!
答案 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,但这可能是最直接的。