Apache camel 聚合多个 REST 服务响应 [英] Apache camel to aggregate multiple REST service responses

查看:37
本文介绍了Apache camel 聚合多个 REST 服务响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 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->返回给客户端.

我现在只有——

<from uri="jetty:http://{host}.{port}./my-service/scan/?matchOnUriPrefix=true&amp;bridgeEndpoint=true"/><!-- 设置特定于服务的标头、监控等.--><!-- 调用 performScan --><to uri="direct:performScan"/></路线><route id="SubRoute_performScan"><from uri="direct:performScan"/><!-- 我该怎么办??进行 callA、callB 服务调用.得到他们的回应 resA、resB.将这些响应聚合到 resScan--></路线>

解决方案

我认为您不必要地使解决方案复杂化了一点.:) 在我看来,调用两个独立远程 Web 服务并连接结果的最佳方法是:

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

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

传递给 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 等).每个组件的程度和动态配置方式各不相同.

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

使用多播端点的 onPrepareRef 选项

预处理传递给每个端点的交换副本.您可以使用它来引用自定义处理器,该处理器将在将负载传递到多播端点之前修改负载.这可能是将 onPrepareRef 与 HTTP 组件的 Exchange.HTTP_URI 标头组合在一起的好方法.

使用收件人列表(也提供了parallelProcessing 以动态创建 REST 端点 URL.

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

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

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

I m new to Camel and wondering how I can implement below mentioned use case using Camel,

We have a REST web service and lets say it has two service operations callA and callB. Now we have ESB layer in the front that intercepts the client requests before hitting this actual web service URLs.

Now I m trying to do something like this - Expose a URL in ESB that client will actually call. In the ESB we are using Camel's Jetty component which just proxies this service call. So lets say this URL be /my-service/scan/

Now on receiving this request @ESB, I want to call these two REST endpoints (callA and callB) -> Get their responses - resA and resB -> Aggregate it to a single response object resScan -> return to the client.

All I have right now is -

<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>

解决方案

I think that you unnecessarily complicate the solution a little bit. :) In my humble opinion the best way to call two independed remote web services and concatenate the results is to:

The routing for the solution above may look like:

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

Exchange passed to the direct:serviceFacadeResponse will contain property Exchange.GROUPED_EXCHANGE set to list of results of calls to your services (Google Search in my example).

And that's how could you wire the direct:serviceFacade to Jetty endpoint:

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

Now all HTTP requests to the service URL exposed by you on ESB using Jetty component will generate responses concatenated from the two calls to the subservices.

Further considerations regarding the dynamic part of messages and endpoints

In many cases using static URL in endpoints is insufficient to achieve what you need. You may also need to prepare payload before passing it to each web service.

Generally speaking - the type of routing used to achieve dynamic endpoints or payloads parameters in highly dependent on the component you use to consume web services (HTTP, CXFRS, Restlet, RSS, etc). Each component varies in the degree and a way in which you can configure it dynamically.

If your endpoints/payloads should be affected dynamically you could also consider the following options:

Preprocess copy of exchange passed to each endpoint using the onPrepareRef option of the Multicast endpoint. You can use it to refer to the custom processor that will modify the payload before passing it to the Multicast's endpoints. This may be good way to compose onPrepareRef with Exchange.HTTP_URI header of HTTP component.

Use Recipient List (which also offers parallelProcessing as the Multicast does) to dynamically create the REST endpoints URLs.

Use Splitter pattern (with parallelProcessing enabled) to split the request into smaller messages dedicated to each service. Once again this option could work pretty well with Exchange.HTTP_URI header of HTTP component. This will work only if both sub-services can be defined using the same endpoint type.

As you can see Camel is pretty flexible and offers you to achieve your goal in many ways. Consider the context of your problem and choose the solution that fits you the best.

If you show me more concrete examples of REST URLs you want to call on each request to the aggregation service I could advice you which solution I will choose and how to implement it. The particularly important is to know which part of the request is dynamic. I also need to know which service consumer you want to use (it will depend on the type of data you will receive from the services).

这篇关于Apache camel 聚合多个 REST 服务响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆