使用 Scala 和 Play2 或 Spray 异步回调



我有一个系统设计挑战,我想得到一些社区反馈。

基本系统结构:

[客户端] ---HTTP-POST--> [REST Service] ---> [队列] ---> [处理器]

  • [客户端] 将 json 发布到 [REST 服务] 进行处理。
  • 根据请求,[Rest Services] 将数据发送到各种队列,由用各种语言编写并在不同进程中运行的各种处理器拾取。
  • 工作在每个处理器中并行化,但仍可能需要长达 30 秒的时间来处理。处理时间是数据复杂性的函数,无法加快。
  • 结果在完成时无法流式传输回客户端,因为有一个最终的后处理步骤,只有在完成所有子步骤后才能完成。

关键挑战:后处理完成后,客户端需要:

  • 在客户端等待后发送结果
  • 异步通知作业已完成,并传递 ID 以请求最终结果

设计要求

我不想阻止 [REST 服务]。 它需要接收传入的请求,将数据路由到适当的队列以便在其他进程中进行处理,然后立即可用于下一个传入请求。

通常我会使用演员和/或期货/承诺,以便在等待后台工作人员完成时不会阻止 [REST 服务]。 这里的挑战是执行后台工作的工作人员在单独的进程/虚拟机中运行,并在各种技术堆栈中编写。 为了在异构系统之间传递这些消息并确保请求生存期的完整性,正在使用持久队列(而不是在内存消息传递或 RPC 中)。

最后一点考虑,为了进行扩展,在各自的池中有一个负载平衡的 [REST 服务] 和 [处理器]。 因此,由于从 [REST 服务] 到 [处理器] 的消息需要通过队列异步发送(并且运行的所有内容都是单独的进程),因此无法将后台 [处理器] 中完成的工作关联回其原始调用 [REST 服务] 实例,以便在承诺或参与者消息中返回最终处理的数据,并最终将响应传递回原始客户端。

那么,问题是,如何建立这种相关性? 完成所有后台处理后,我需要通过等待已久的响应或通知将结果返回给客户端(我不想使用 UrbanAirship 之类的东西,因为大多数客户端都是浏览器或其他服务。

我希望这是清楚的,如果没有,请要求澄清。

编辑:可能的解决方案 - 想法?

我想我将一个喷雾 RequestContext 传递给任何参与者,然后它可以响应回客户端(不必是收到 HTTP 请求的原始参与者)。 如果为真,我是否可以缓存 RequestContext,然后在处理完成后使用它使用此缓存的请求上下文将响应异步发送到相应的客户端?

好吧,这不是最好的,因为它需要客户端进行更多工作,但听起来您想实现 webhook。 所以

[客户端] --- POST--> [REST 服务] ---> [计算] ---> POST [客户端]

[客户端] --- GET

解释:客户端向服务发送 POST 请求。 然后,您的服务会执行任何必要的处理。 完成后,您的服务会将 HTTP-POST 发送到客户端已设置的 URL。 使用该 POST 数据,客户端将获得必要的信息,然后对完成的数据执行 GET 请求。

最新更新