【问题标题】:Synchronous, Asynchronous and Command Client Requests with GWT and GAE使用 GWT 和 GAE 的同步、异步和命令客户端请求
【发布时间】:2012-09-02 02:12:06
【问题描述】:

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

  • 同步 - “回答我现在!我很重要,需要实时响应!!!”
  • 异步 - “尽可能回复我;我需要在某个时候知道答案,但实际上并不是那么紧急。”
  • 命令 - “我不需要答案。这不是真正的请求,它只是在服务器端执行某事或处理某事的命令。”

我的游戏计划是实现我的 GWT 代码,以便我可以为每个特定的服务器端请求指定(注意:我决定使用 RequestFactory 而不是传统的GWT-RPC 出于此问题范围之外的原因),它是哪种类型的请求:

  • SynchronousRequest - 同步(从上方);发送命令并急切地等待响应,然后以某种方式更新客户端的状态
  • AsynchronousRequest - 异步(从上面);发出初始请求,并以某种方式(通过轮询或 GAE 通道 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 强加的规定)。

那么,这就是我在这里真正要问的:

  • 如何将RequestFactory 调用封装在SynchronousRequestAsynchronousRequestCommandRequest 中,使RequestFactory 调用的行为符合它们各自的预期方式?换句话说,这样调用要么部分阻塞(同步),要么可以在以后的某个时间通知/更新(异步),还是可以只是触发后忘记(命令)?
  • 如何实现我的要求,让 SynchronousRequest 绕过 GAE 的 60 秒超时,并且仍然得到处理而不会失败?

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

【问题讨论】:

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


    【解决方案1】:

    如果您希望 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 获得更快的馈送速度。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-31
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 1970-01-01
      • 1970-01-01
      • 2014-08-06
      相关资源
      最近更新 更多