Spring集成-拆分后发布publishSubscribeChannel聚合

时间:2018-06-27 09:53:26

标签: spring-integration spring-integration-dsl

我有一个基于DSL的流,它使用split遍历对象列表并发出Kafka消息:

.transform(...)
.split()
.channel(KAFKA_OUT_CHANNEL)

发送完所有消息后,我需要致电服务,还需要记录已处理的消息数。 我了解一种方法是使用publishSubscribeChannel,其中第一个subscribe执行实际的Kafka发送,然后aggregate执行服务调用:

.transform(...)
.split().
.publishSubscribeChannel(pubSub -> pubSub
        .subscribe(f -> f.channel(KAFKA_OUT_CHANNEL)))

我在弄清楚如何使用DSL实际完成pubSubChannel中的.aggregate部分时遇到了问题。到目前为止,我已经尝试过:

.subscribe(f ->  f.channel(KAFKA_OUT_CHANNEL)
.subscribe(f -> f.aggregate(c -> c.processor( ?? ))))

有指针吗?

2 个答案:

答案 0 :(得分:0)

AbstractMessageSplitter默认有一个applySequence = true

/**
 * Set the applySequence flag to the specified value. Defaults to true.
 * @param applySequence true to apply sequence information.
 */
public void setApplySequence(boolean applySequence) {

我们在消息中包含以下标头:

if (this.applySequence) {
    builder.pushSequenceDetails(correlationId, sequenceNumber, sequenceSize);
}

聚合器的默认关联策略实际上基于IntegrationMessageHeaderAccessor.CORRELATION_ID标头。这样,它将具有相同correlationKey的消息收集到相同的MessageGroup中。默认ReleaseStrategy基于MessageGroup和该sequenceSize标头比较。最后,默认的MessageGroupProcessor仅将组中的所有消息收集为一条消息,并以Collection作为有效负载。换句话说,聚合器的默认行为与拆分器完全相反。

我不知道您要从聚合器执行的输出,但是您不需要在此配置任何其他逻辑-相关性和释放逻辑应基于默认状态。

您可以在Reference Manual中找到足够的信息。

答案 1 :(得分:0)

这取决于聚合后想要的内容-如果您只想要有效负载列表,只需使用aggregate() ...

@SpringBootApplication
public class So51059703Application {

    public static void main(String[] args) {
        SpringApplication.run(So51059703Application.class, args);
    }

    @Bean
    public ApplicationRunner runner(ApplicationContext context) {
        return args -> {
            context.getBean("flow.input", MessageChannel.class).send(new GenericMessage<>(
                    Arrays.asList("a", "b", "c")));
        };
    }

    @Bean
    public IntegrationFlow flow() {
        return f -> f
                .split()
                .publishSubscribeChannel(p -> p
                        .subscribe(f1 -> f1.handle(System.out::println))
                        .subscribe(f2 -> f2
                                .aggregate()
                                .handle(System.out::println)));
    }

}

如果您只想计数:

@SpringBootApplication
public class So51059703Application {

    public static void main(String[] args) {
        SpringApplication.run(So51059703Application.class, args);
    }

    @Bean
    public ApplicationRunner runner(ApplicationContext context) {
        return args -> {
            context.getBean("flow.input", MessageChannel.class).send(new GenericMessage<>(
                    Arrays.asList("a", "b", "c")));
        };
    }

    @Bean
    public IntegrationFlow flow() {
        return f -> f
                .split()
                .publishSubscribeChannel(p -> p
                        .subscribe(f1 -> f1.handle(System.out::println))
                        .subscribe(f2 -> f2
                                .aggregate(c -> c
                                        .processor(processor(), "reduce"))
                                .handle(System.out::println)));
    }

    @Bean
    public Object processor() {
        return new Object() {

            public int reduce(List<Message<?>> messages) {
                return messages.size();
            }

        };
    }

}