Apache驼峰聚合多个REST服务响应

时间:2012-05-16 01:14:10

标签: web-services rest apache-camel esb aggregation

我是Camel的新手,想知道如何使用Camel实现下面提到的用例,

我们有一个REST Web服务,让我们说它有两个服务操作callA和callB。 现在我们在前面有ESB层,在访问这些实际的Web服务URL之前拦截客户端请求。

现在我想尝试这样的事情 - 在客户端实际调用的ESB中公开URL。在ESB中,我们使用的是Camel的Jetty组件,它只代理此服务调用。所以我们假设这个URL是/ my-service / scan /

现在收到此请求@ESB后,我想调用这两个REST端点(callA和callB) - >得到他们的回复 - resA和resB - >将其聚合到单个响应对象resScan - >回到客户端。

我现在所拥有的只是 -

<route id="MyServiceScanRoute">
<from uri="jetty:http://{host}.{port}./my-service/scan/?matchOnUriPrefix=true&amp;bridgeEndpoint=true"/>
<!-- Set service specific headers, monitoring etc. -->  
<!-- Call performScan -->
<to uri="direct:performScan"/>
</route>

<route id="SubRoute_performScan">
<from uri="direct:performScan"/>
<!--  HOW DO I??
Make callA, callB service calls. 
Get their responses resA, resB.
Aggregate these responses to resScan
 -->
</route>

2 个答案:

答案 0 :(得分:15)

我认为你不必要地使解决方案变得复杂一点。 :)以我的拙见,调用两个独立远程Web服务并连接结果的最佳方法是:

上述解决方案的路由可能如下所示:

from("direct:serviceFacade")
  .multicast(new GroupedExchangeAggregationStrategy()).parallelProcessing()
    .enrich("http://google.com?q=Foo").enrich("http://google.com?q=Bar")
  .end();

传递给direct:serviceFacadeResponse的Exchange将包含设置为服务调用结果列表的属性Exchange.GROUPED_EXCHANGE(在我的示例中为Google搜索)。

这就是你如何将direct:serviceFacade连接到Jetty端点:

from("jetty:http://0.0.0.0:8080/myapp/myComplexService").enrich("direct:serviceFacade").setBody(property(Exchange.GROUPED_EXCHANGE));

现在,您在使用Jetty组件的ESB上公开的服务URL的所有HTTP请求都将生成从对子服务的两次调用连接的响应。

有关消息和端点动态部分的进一步注意事项

在许多情况下,在端点中使用静态URL不足以实现您的需求。您可能还需要在将有效负载传递给每个Web服务之前进行准备。

一般而言 - 用于实现动态端点或有效负载参数的路由类型高度依赖于您用于使用Web服务的组件(HTTPCXFRSRestlet,RSS等)。每个组件的程度和方式都有所不同,可以动态配置它。

如果您的端点/有效负载应该受到动态影响,您还可以考虑以下选项:

使用Multicast端点的onPrepareRef选项传递到每个端点的交换的预处理副本。您可以使用它来引用将在将有效负载传递到多播的端点之前修改有效负载的自定义处理器。这可能是使用HTTP组件的Exchange.HTTP_URI标头编写onPrepareRef的好方法。

使用Recipient List (也提供parallelProcessing,如多播一样)来动态创建REST端点网址。

使用Splitter模式(启用parallelProcessing)将请求拆分为专用于每项服务的较小消息。再次,此选项可以与HTTP组件的Exchange.HTTP_URI标头很好地协作。只有在使用相同的端点类型定义两个子服务时,这才有效。

正如您所看到的,Camel非常灵活,可以让您以多种方式实现目标。考虑问题的背景,选择最适合您的解决方案。

如果你向我展示你想要在聚合服务的每个请求上调用的REST URL的更具体的例子,我可以建议你选择哪种解决方案以及如何实现它。特别重要的是要知道请求的哪一部分是动态的。我还需要知道您要使用哪个服务使用者(这取决于您将从服务中获得的数据类型)。

答案 1 :(得分:2)

这看起来是一个应该使用Content Enricher模式的好例子。 Described here

<from uri="direct:performScan"/>
   <enrich uri="ServiceA_Uri_Here" strategyRef="aggregateRequestAndA"/>
   <enrich uri="ServiceA_Uri_Here" strategyRef="aggregateAandB"/>
</route>

聚合策略必须用Java编写(或者也许是一些脚本语言,Scala / groovy? - 但我还没试过)。

聚合策略只需要是一个实现org.apache.camel.processor.aggregate.AggregationStrategy的bean,它反过来要求你实现一个方法:

Exchange aggregate(Exchange oldExchange, Exchange newExchange);

因此,现在由您将请求与来自富访服务调用的响应合并。你必须做两次,因为你有callA和callB。您可能会或可能找不到两种预定义的聚合策略,即UseLatestAggregationStrategy和UseOriginalAggregationStrategy。这些名字是非常自我解释的。

祝你好运