用于昂贵请求的请求聚合器/中间层设计模式

本文关键字:请求 中间层 设计模式 用于 | 更新日期: 2023-09-27 17:53:30

我正在研究一个程序,该程序将有多个线程需要来自web服务的信息,可以处理以下请求:"用[Var1, Var2, Var3][Object1, Object2, ... Object20] "

和结果的回复将给我一个,在本例中,20个节点的XML(每个对象一个),每个节点有3个子节点(每个变量一个)。

我的挑战是,这个web服务的每个请求都要花费组织的钱,无论是1个对象的1个变量还是20个对象的20个变量,成本都是一样的。

所以,在这种情况下,我正在寻找一个架构,将:

  1. 在每个线程上创建一个需要数据的请求
  2. 有一个中间层的"聚合器"来获取所有的请求
  3. 一旦聚合了X数量的请求(或达到了时间限制),中间层执行web服务的单个请求
  4. 中间层接收到web-service的应答
  5. 中间层路由信息返回到等待对象

目前,我的想法是使用像NetMQ这样的库,我的中间层作为服务器,每个线程作为轮询器,但我在实际实现中卡住了,在深入兔子洞之前,我希望已经有一个设计模式/库,它比我想象的要有效得多。

请理解,我是一个新手,所以,任何帮助/指导将是非常感激的!!

谢谢! !

用于昂贵请求的请求聚合器/中间层设计模式

概述

从体系结构的角度来看,您刚刚为这个问题勾画出了一个很好的方法:

  1. 在请求应用程序和远程web服务之间插入代理
  2. 在代理中,将请求放入请求队列,直到至少发生以下事件之一
    1. 请求队列达到给定长度
    2. 请求队列中最老的请求达到一定年龄
  3. 将请求队列中的所有请求分组为一个请求,删除重复的对象或属性
  4. 将此请求发送到远程web服务
  5. 将请求移动到(等待)响应队列
  6. 等待响应,直到出现以下情况之一
    1. 响应队列中最老的请求达到一定年龄(超时)
    2. 响应到达
  7. 获取响应(如果适用)并将其映射到响应队列中的相应请求
  8. 响应队列中具有应答
  9. 的所有请求
  10. 为所有超过超时限制的请求发送超时错误
  11. 从响应队列中删除所有已应答的请求
<标题> 技术

你可能找不到一个现成的产品或框架完全符合你的需求。但是有几个框架/架构模式可以用来构建解决方案。

c#: RX and LINQ

当你想使用c#时,你可以使用响应式扩展来获得正确的计时和分组。

然后,您可以使用LINQ从请求中选择属性来构建响应,并在响应队列中选择与响应的特定部分匹配或超时的请求。

Scala

/Java: Akka

您可以将解决方案建模为一个参与者系统,使用几个参与者:

  1. 作为请求的网关的参与者
  2. 持有请求队列的参与者
  3. 向远程web服务发送请求并获得响应的参与者
  4. 持有响应队列的参与者
  5. 发送响应或超时的参与者

参与者系统使并发处理和以可测试的方式分离关注点变得容易。

当使用Scala时,你可以使用它的"一元"集合API (filter, map, flatMap)来做与c#方法中的LINQ基本相同的事情。

当您想要测试单个元素时,actor方法确实很好用。单独测试每个参与者是非常容易的,而不必模拟整个工作流程。

Erlang/Elixir: Actor System

这类似于Akka方法,只是使用了不同的(函数式的!)语言。Erlang/Elixir对分布式参与者系统有很多支持,所以当你需要一个超级稳定或可扩展的解决方案时,你应该考虑一下这个。

NetMQ/ZeroMQ

这可能是太低的水平,并带来了很少的基础设施。当您使用参与者系统时,您可以尝试引入NetMQ/ZeroMQ作为传输系统。

我觉得你使用队列的想法不错。

这是你问题的一个可能的解决方案,我相信还有无数其他的解决方案可以满足你的需要。

  1. 有一个"发布队列"(PQ)和一个"消费队列"(CQ)
  2. 客户端订阅CQ, MT订阅PQ
  3. 客户端向PQ发布请求
  4. MT监听PQ,聚合请求和调度到线程中的farm
  5. 一旦结果返回,该线程将结果分离到req/res对
  6. 然后将请求/res对发布到CQ
  7. 每个客户端选择正确的消息并处理它

长(er)版本:

让你的"中间层"监听一个队列(客户端向其发布消息)并聚合请求,直到N个请求通过或X个时间过去。

准备好后,将聚合的请求卸载到一个线程来调用您的farm并获得结果。当您需要将此信息反馈给客户端时,很可能会出现更大的问题。

为此,您可能需要另一个所有客户端都订阅的队列,一旦您的结果批处理就绪(例如20个XML响应),调用该队列的线程将把XML结果分离到相应的请求/响应对中,并发布到该队列。每个客户端都需要从队列中获取正确的请求/响应对并对其进行处理。

这将不是传统意义上的web服务,因为等待时间可能会非常长,并且您不想维护连接,这就是我建议使用队列的原因。

你也可以让你的消费者队列是基于主题的,这意味着你只发布请求的req/res对的消费者,而不广播它(所以客户端不必"选择正确的req/res")。它将根据主题名称进行处理)。