分裂后并行丰富

时间:2016-07-22 10:07:14

标签: spring-integration

这是shopping cart sample的延续,我们有一个外部API,允许从购物车结帐。回顾一下,我们有一个流程,我们创建一个空的购物,添加行项目,最后结帐。上面的所有操作都是通过HTTP调用外部服务来实现的。我们想要同时添加订单项(作为添加订单项的一部分)调用。我们当前的配置如下所示:

@Bean
public IntegrationFlow fullCheckoutFlow() {
    return f -> f.channel("inputChannel")
            .transform(fromJson(ShoppingCart.class))
            .enrich(e -> e.requestChannel(SHOPPING_CART_CHANNEL))
            .split(ShoppingCart.class, ShoppingCart::getLineItems)
            .enrich(e -> e.requestChannel(ADD_LINE_ITEM_CHANNEL))
            .aggregate(aggregator -> aggregator
                    .outputProcessor(g -> g.getMessages()
                            .stream()
                            .map(m -> (LineItem) m.getPayload())
                            .map(LineItem::getName)
                            .collect(joining(", "))))
            .enrich(e -> e.requestChannel(CHECKOUT_CHANNEL))
            .<String>handle((p, h) -> Message.called("We have " + p + " line items!!"));
}

    @Bean
    public IntegrationFlow addLineItem(Executor executor) {
        return f -> f.channel(MessageChannels.executor(ADD_LINE_ITEM_CHANNEL, executor).get())
                .handle(outboundGateway("http://localhost:8080/api/add-line-item", restTemplate())
                        .httpMethod(POST)
                        .expectedResponseType(String.class));
    }

    @Bean
    public Executor executor(Tracer tracer, TraceKeys traceKeys, SpanNamer spanNamer) {
        return new TraceableExecutorService(newFixedThreadPool(10), tracer, traceKeys, spanNamer);
    }

@Bean public IntegrationFlow fullCheckoutFlow() { return f -> f.channel("inputChannel") .transform(fromJson(ShoppingCart.class)) .enrich(e -> e.requestChannel(SHOPPING_CART_CHANNEL)) .split(ShoppingCart.class, ShoppingCart::getLineItems) .enrich(e -> e.requestChannel(ADD_LINE_ITEM_CHANNEL)) .aggregate(aggregator -> aggregator .outputProcessor(g -> g.getMessages() .stream() .map(m -> (LineItem) m.getPayload()) .map(LineItem::getName) .collect(joining(", ")))) .enrich(e -> e.requestChannel(CHECKOUT_CHANNEL)) .<String>handle((p, h) -> Message.called("We have " + p + " line items!!")); } @Bean public IntegrationFlow addLineItem(Executor executor) { return f -> f.channel(MessageChannels.executor(ADD_LINE_ITEM_CHANNEL, executor).get()) .handle(outboundGateway("http://localhost:8080/api/add-line-item", restTemplate()) .httpMethod(POST) .expectedResponseType(String.class)); } @Bean public Executor executor(Tracer tracer, TraceKeys traceKeys, SpanNamer spanNamer) { return new TraceableExecutorService(newFixedThreadPool(10), tracer, traceKeys, spanNamer); }

要并行添加订单项,我们正在使用执行程序渠道。但是,在zipkin中看到它们似乎仍然是按顺序处理的:

Zipkin trace

我们做错了什么?整个项目的来源位于github以供参考。

谢谢!

1 个答案:

答案 0 :(得分:1)

首先,Spring Integration的主要功能是MessageChannel,但我仍然不清楚为什么人们在端点定义之间缺少.channel()运算符。

我的意思是,对于你的情况,它必须是:

.split(ShoppingCart.class, ShoppingCart::getLineItems)
.channel(c -> c.executor(executor()))
.enrich(e -> e.requestChannel(ADD_LINE_ITEM_CHANNEL))

现在关于你的特殊问题。

看,ContentEnricher.enrich())是请求 - 回复组件:http://docs.spring.io/spring-integration/reference/html/messaging-transformation-chapter.html#payload-enricher

因此,它向requestChannel发送请求并等待回复。它独立于requestChannel类型完成。

我是原始Java,我们可以使用此代码片段演示此类行为:

for (Object item: items) {
    Data data = sendAndReceive(item);
}

您应该看到ADD_LINE_ITEM_CHANNEL ExecutorChannel作为.split()的价值不大,因为无论如何我们都会在循环中被阻止。

DirectChannel执行完全相似的循环,但由于默认情况下它与.enrich()一致,因此迭代在同一个线程中完成。因此,每个下一个项目都会等待前一个项目的回复。

这就是为什么你绝对应该在.split()之后完全与function getPopularMovies() { var deferred = $q.defer(); var popularmoviesurl = "https://api.themoviedb.org/3/movie/popular?api_key=adf3d78d5c0f38313a68de730f02063a"; $http({method:'GET',url:popularmoviesurl}). success(function (data, status, headers, config) { if (status == 200) { deferred.resolve(data.results); } else { console.error('Error happened while getting the movie list.') deferred.reject(); } }).error(function (data, status, headers, config) { deferred.reject(); console.error('Error happened while getting the movie list.') }); return deferred.promise; } 的输入并行。