繁体   English   中英

如何使用Spring Integration处理来自AWS SQS FiFo队列的10多个并发消息

[英]How to process more than 10 concurrent messages from an AWS SQS FiFo queue using Spring Integration

我希望能够使用Spring Integration Workflow一次处理10个以上的SQS消息。

从这个问题,建议是使用ExecutorChannel 我更新了我的代码,但仍然有相同的症状。

如何在多个线程中执行Spring集成流以并行消耗更多Amazon SQS队列消息?

进行此更新后,我的应用程序请求10条消息,处理这些消息,并且只有在流程结束后调用amazonSQSClient.deleteMessage之后,它才会接受来自SQS队列的另外10条消息。

该应用程序使用SQS FiFo队列。

还有其他我缺少的东西,或者这是使用SqsMessageDeletionPolicy.NEVER然后在流程结束时删除消息的不可避免的症状? 由于其他约束,在流程开始时接受消息实际上不是一个选项。

以下是相关的代码片段,有一些简化,但我希望它表达了这个问题。

队列配置

@Bean
public AsyncTaskExecutor inputChannelTaskExecutor() {
    SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
    executor.setConcurrencyLimit(50);
    return executor;
}

@Bean
@Qualifier("inputChannel")
public ExecutorChannel inputChannel() {
    return new ExecutorChannel(inputChannelTaskExecutor());
}

我也试过一个ThreadPoolTask​​Executor而不是SimpleAsyncTaskExecutor,结果相同,但我也会包括它,以防它提供其他见解。

    @Bean
    public AsyncTaskExecutor inputChannelTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(50);
        executor.setQueueCapacity(50);
        executor.setThreadNamePrefix("spring-async-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.afterPropertiesSet();
        executor.initialize();
        return executor;
    }

SQS通道适配器

@Bean
public SqsMessageDrivenChannelAdapter changeQueueMessageAdapter() {
    SqsMessageDrivenChannelAdapter adapter = new SqsMessageDrivenChannelAdapter(this.amazonSQSClient, changeQueue);
    adapter.setOutputChannel(inputChannel);
    adapter.setMessageDeletionPolicy(SqsMessageDeletionPolicy.NEVER);
    return adapter;
}


@Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerSpec poller() {
    return Pollers.fixedRate(500, TimeUnit.MILLISECONDS).maxMessagesPerPoll(10);
}

简化主流程

我们的一个常见场景是在短时间内获得一些分支编辑。 此流程仅“关注”至少发生了一次编辑。 messageTransformer从有效负载文档中提取一个id并将其放入标题dsp_docId中 ,然后我们用它来聚合(我们在其他几个地方使用这个id,所以我们认为标题有意义而不是在自定义中完成所有工作聚合器)。

provisioningServiceActivator检索最新版本的分支,然后路由器决定是否需要进一步转换(在这种情况下它将其发送到transformBranchChannel ),或者它可以发送到我们的PI实例(通过sendToPiChannel)。

转换流程(未显示,我认为您不需要它)导致最终发送到PI流程,它只是先做更多的工作。

listingGroupProcessor捕获所有aws_receiptHandle标头,并将它们作为|添加到新标头中 分开的清单。

sendToPi流(和errorFlow)以对自定义处理程序的调用结束,该处理程序负责删除该aws_receiptHandle字符串列表引用的所有SQS消息。

@Bean
IntegrationFlow sqsListener() {
    return IntegrationFlows.from(inputChannel)
                           .transform(messageTransformer)
                           .aggregate(a -> a.correlationExpression("1")
                                            .outputProcessor(listingGroupProcessor)
                                            .autoStartup(true)
                                            .correlationStrategy(message -> message.getHeaders().get("dsp_docId"))
                                            .groupTimeout(messageAggregateTimeout)  // currently 25s
                                            .expireGroupsUponCompletion(true)
                                            .sendPartialResultOnExpiry(true)
                                            .get())

                           .handle(provisioningServiceActivator, "handleStandard")
                           .route(Branch.class, branch -> (branch.isSuppressed() == null || !branch.isSuppressed()),
                                  routerSpec -> routerSpec.channelMapping(true, "transformBranchChannel")
                                                          .resolutionRequired(false)
                                                          .defaultOutputToParentFlow())

                           .channel(sendtoPiChannel)
                           .get();
}

我以为我会把这个作为答案发布,因为这解决了我的问题,可能会帮助别人。 作为答案,它更容易被发现,而不是可能被忽视的原始问题的编辑。

首先,我应该注意到我们正在使用FiFo队列。

问题实际上是在链中,我们将MessageGroupId设置为描述数据源的简单值。 这意味着我们有非常大的消息组。

ReceiveMessage文档中,您可以看到它非常明智地阻止您在此方案中请求来自该组的更多消息,因为如果需要将消息放回队列,则无法保证订单。

更新发布消息的代码以设置适当的MessageGroupId然后意味着ExecutorChannel按预期工作。

虽然具有特定MessageGroupId的消息是不可见的,但在可见性超时到期之前,不会再返回属于同一MessageGroupId的消息。 只要它也可见,您仍然可以使用另一个MessageGroupId接收消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM