Camel - 使用Java DSL进行并行GET请求并通过动态路由聚合结果

时间:2016-10-18 10:42:01

标签: rest apache-camel jetty

我正在Jetty Http端点上收到请求。请求正文包含请求正文中的一些网址。我必须向这些网址发出GET请求。然后聚合每个GET请求的结果并将其返回给调用者。

申请机构: -

{
    "data" : [
        {"name" : "Hello", "url" : "http://server1"}
        {"name" : "Hello2", "url" : "http://server2"}

    ]
}

我可以想到这样做的一种方式如下: -

from("jetty:http://localhost:8888/hello").process(new Processor() {
    public void process(Exchange exchange) throws Exception {
        // 1. Make the GET request in parallel using ThreadPoolExecutor
        // 2. Wait for all calls to finish. Collate the response
        // 3. Write it to exchange.getOut().setBody
    }
})

如果可以通过使用camel Dynamic Routes,Splitter& amp;的Java DSL实现这一目标,有人可以告诉我。聚合器使Processor仍然相对较小?

我使用的是camel 2.16.3。

2 个答案:

答案 0 :(得分:2)

步骤如下:

  1. 将传入的数据拆分为URL。这可能涉及子步骤:for 例如,您可以将传入的JSON字符串解组为某个POJO,并且此POJO可能有一个数组或列表,其中每个条目都是一个URL。然后,你可以将它传递给身体。 (当然,您可能需要传入请求中的其他信息,因此您可以对此进行更改。)
  2. 如果主体是一个数组或其他可以轻松处理的东西,分割器就会很容易分裂。在最简单的情况下,拆分器将传递每个拆分消息正文中的单个URI。
  3. 下一步 - 在分割器的流程中 - 您可以拥有像http4这样的生产者,但是您可以要求它在消息中使用URI,而不是使用端点上的URI。
  4. 最后,你会有一个聚合器。
  5. 听起来你的问题的核心是动态URI。这就是代码片段的外观:

     from(...)... etc. 
        .setHeader(Exchange.HTTP_URI, simple("${body}"))
        .setHeader(Exchange.HTTP_METHOD,  
                  constant(org.apache.camel.component.http4.HttpMethods.GET))
        .to("http4://google.com")
    

    对于小型工作演示,see this class

    public class HttpDynamicClient extends RouteBuilder {
    
        @Override
        public void configure() throws Exception {
    
            from("direct:testMultiple")
            .split(body())
            .to("direct:httpClient");
    
            from("direct:httpClient")
            .log("starting httpClient route")
            .setHeader(Exchange.HTTP_URI, simple("${body}"))
            .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http4.HttpMethods.GET))
            .to("http4://google.com")
            .process(new BodyToStringConverter())
            .log(LoggingLevel.INFO, "Output was ${body}");
        }
    
        private static class BodyToStringConverter implements Processor {
            @Override
            public void process(Exchange exchange) throws Exception {
                exchange.getOut().setBody(exchange.getIn().getBody(String.class));
            }
        }
    
    
        public static void main(String[] args) throws Exception {
            CamelContext context = new DefaultCamelContext();
            try {
                Logger logger = Logger.getLogger(HttpDynamicClient.class);
    
                context.addRoutes(new HttpDynamicClient());
                ProducerTemplate template = context.createProducerTemplate();
                context.start();
                Thread.sleep(1000);
    
    
                template.sendBody("direct:httpClient", "http://jsonplaceholder.typicode.com/posts/1");
                Thread.sleep(2000);
    
                template.sendBody("direct:testMultiple", new String [] {"http://jsonplaceholder.typicode.com/posts/1" , "http://jsonplaceholder.typicode.com/posts/1"});
    
    
            } finally {
                context.stop();
            }
        }
    
    }
    

答案 1 :(得分:2)

@Darius X的答案非常符合你的需要。要使后端请求并行执行并在字符串列表中聚合响应主体,您需要设置聚合策略并在拆分定义上设置并行处理标志。

@Override
public void configure() throws Exception {

    from("direct:testMultiple")
            .split(body(), new FlexibleAggregationStrategy<String>()
                    .pick(Builder.body())
                    .castAs(String.class)
                    .accumulateInCollection(ArrayList.class))
            .parallelProcessing()
            // .executorService(<instance of java.util.concurrent.ExecutorService>) // optional: use custom thread pool for parallel processing
            .to("direct:httpClient");

    from("direct:httpClient")
            .log("starting httpClient route")
            .setHeader(Exchange.HTTP_URI, simple("${body}"))
            .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http4.HttpMethods.GET))
            .to("http4://google.com")
            .convertBodyTo(String.class)
            .log(LoggingLevel.INFO, "Output was ${body}");
}

direct:testMultiple返回的交换消息将包含您的结果数组作为正文。