Spring integration Spring集成:如何增加传入消息的处理

Spring integration Spring集成:如何增加传入消息的处理,spring-integration,poller,Spring Integration,Poller,我正在开发一个Spring应用程序,它每分钟将接收大约500条xml消息。下面的xml配置只允许每分钟处理大约60条消息,其余消息存储在队列中(持久化在DB中),并以每分钟60条消息的速率检索 尝试从多个来源阅读文档,但仍然不清楚轮询器和任务执行器的角色。我对当前每分钟处理60条消息的理解是因为轮询器配置中的“固定延迟”值设置为10(因此它将在1分钟内轮询6次),“每轮询最大消息数”设置为10,因此6x10=每分钟处理60条消息 如果我的理解不正确,请提供建议,并帮助修改xml配置,以实现以更高

我正在开发一个Spring应用程序,它每分钟将接收大约500条xml消息。下面的xml配置只允许每分钟处理大约60条消息,其余消息存储在队列中(持久化在DB中),并以每分钟60条消息的速率检索

尝试从多个来源阅读文档,但仍然不清楚轮询器和任务执行器的角色。我对当前每分钟处理60条消息的理解是因为轮询器配置中的“固定延迟”值设置为10(因此它将在1分钟内轮询6次),“每轮询最大消息数”设置为10,因此6x10=每分钟处理60条消息

如果我的理解不正确,请提供建议,并帮助修改xml配置,以实现以更高的速率处理传入消息

任务执行器的角色也不清楚-这是否意味着pool size=“50”将允许50个线程并行运行以处理轮询器轮询的消息

我想要的是:

  • JdbcChannelMessageStore用于将传入的xml消息存储在数据库(INT_CHANNEL_MESSAGE)表中。这是必需的,以便在服务器重新启动时,消息仍存储在表中,不会丢失
  • 以受控/有限数量并行执行的传入消息。基于系统处理这些消息的能力,我想限制系统应该并行处理多少消息
  • 由于此配置将在群集中的多个服务器上使用,因此任何服务器都可以拾取任何消息,因此不会导致两个服务器处理的同一消息发生任何冲突。希望Spring集成能够解决这个问题
  • 抱歉,如果这已经在别处得到了回答,但在阅读了大量帖子后,我仍然不明白这是怎么回事

    提前谢谢

    <!-- Message Store configuration start -->              
    
        <!-- JDBC message store configuration -->
        <bean id="store" class="org.springframework.integration.jdbc.store.JdbcChannelMessageStore">
            <property name="dataSource" ref="dataSource"/>
            <property name="channelMessageStoreQueryProvider" ref="queryProvider"/>
            <property name="region" value="TX_TIMEOUT"/>
            <property name="usingIdCache" value="true"/>
        </bean>
    
        <bean id="queryProvider" class="org.springframework.integration.jdbc.store.channel.MySqlChannelMessageStoreQueryProvider" />        
    
    <int:transaction-synchronization-factory
        id="syncFactory">
        <int:after-commit expression="@store.removeFromIdCache(headers.id.toString())" />
        <int:after-rollback expression="@store.removeFromIdCache(headers.id.toString())" />
    </int:transaction-synchronization-factory>
    
    <task:executor id="pool" pool-size="50" queue-capacity="100" rejection-policy="CALLER_RUNS" />  
    
    <int:poller id="messageStorePoller" fixed-delay="10"
        receive-timeout="500" max-messages-per-poll="10" task-executor="pool"
        default="true" time-unit="SECONDS">
        <int:transactional propagation="REQUIRED"
            synchronization-factory="syncFactory" isolation="READ_COMMITTED"
            transaction-manager="transactionManager" /> 
    </int:poller>
    
    <bean id="transactionManager"
        class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
    
    
    
    
    
    在Artem回复后添加:

    谢谢你,阿泰姆。因此,在固定延迟10秒后发生的每次轮询(根据上面的配置),任务执行者将检查任务队列,如果可能(并且需要),启动一个新任务?每个轮询任务(线程)将从消息存储(队列)接收“10”条消息,按照“maxMessagesPerPoll”配置

    为了获得更高的传入消息处理时间,我是否应该减少轮询器上的固定延迟,以便任务执行器可以启动更多线程?如果我将fixedDelay设置为2秒,将启动一个新线程来执行10条消息,一分钟内将启动大约30个这样的线程,一分钟内处理“大约”300条传入消息


    很抱歉在一个问题中问得太多-只是想解释完整的问题。

    本课程的主要逻辑是:

        private final class Poller implements Runnable {
    
        private final Callable<Boolean> pollingTask;
    
        Poller(Callable<Boolean> pollingTask) {
            this.pollingTask = pollingTask;
        }
    
        @Override
        public void run() {
            AbstractPollingEndpoint.this.taskExecutor.execute(() -> {
                int count = 0;
                while (AbstractPollingEndpoint.this.initialized
                        && (AbstractPollingEndpoint.this.maxMessagesPerPoll <= 0
                        || count < AbstractPollingEndpoint.this.maxMessagesPerPoll)) {
                    try {
                        if (!Poller.this.pollingTask.call()) {
                            break;
                        }
                        count++;
                    }
                    catch (Exception e) {
                        if (e instanceof MessagingException) {
                            throw (MessagingException) e;
                        }
                        else {
                            Message<?> failedMessage = null;
                            if (AbstractPollingEndpoint.this.transactionSynchronizationFactory != null) {
                                Object resource = TransactionSynchronizationManager.getResource(getResourceToBind());
                                if (resource instanceof IntegrationResourceHolder) {
                                    failedMessage = ((IntegrationResourceHolder) resource).getMessage();
                                }
                            }
                            throw new MessagingException(failedMessage, e);
                        }
                    }
                    finally {
                        if (AbstractPollingEndpoint.this.transactionSynchronizationFactory != null) {
                            Object resource = getResourceToBind();
                            if (TransactionSynchronizationManager.hasResource(resource)) {
                                TransactionSynchronizationManager.unbindResource(resource);
                            }
                        }
                    }
                }
            });
        }
    
    }
    
    私有最终类轮询器实现可运行{
    私有最终可调用轮询任务;
    轮询器(可调用轮询任务){
    this.pollingTask=pollingTask;
    }
    @凌驾
    公开募捐{
    AbstractPollingEndpoint.this.taskExecutor.execute(()->{
    整数计数=0;
    while(AbstractPollingEndpoint.this.initialized
    
    &&(AbstractPollingEndpoint.this.maxMessagesPerPoll主要逻辑在此类后面:

        private final class Poller implements Runnable {
    
        private final Callable<Boolean> pollingTask;
    
        Poller(Callable<Boolean> pollingTask) {
            this.pollingTask = pollingTask;
        }
    
        @Override
        public void run() {
            AbstractPollingEndpoint.this.taskExecutor.execute(() -> {
                int count = 0;
                while (AbstractPollingEndpoint.this.initialized
                        && (AbstractPollingEndpoint.this.maxMessagesPerPoll <= 0
                        || count < AbstractPollingEndpoint.this.maxMessagesPerPoll)) {
                    try {
                        if (!Poller.this.pollingTask.call()) {
                            break;
                        }
                        count++;
                    }
                    catch (Exception e) {
                        if (e instanceof MessagingException) {
                            throw (MessagingException) e;
                        }
                        else {
                            Message<?> failedMessage = null;
                            if (AbstractPollingEndpoint.this.transactionSynchronizationFactory != null) {
                                Object resource = TransactionSynchronizationManager.getResource(getResourceToBind());
                                if (resource instanceof IntegrationResourceHolder) {
                                    failedMessage = ((IntegrationResourceHolder) resource).getMessage();
                                }
                            }
                            throw new MessagingException(failedMessage, e);
                        }
                    }
                    finally {
                        if (AbstractPollingEndpoint.this.transactionSynchronizationFactory != null) {
                            Object resource = getResourceToBind();
                            if (TransactionSynchronizationManager.hasResource(resource)) {
                                TransactionSynchronizationManager.unbindResource(resource);
                            }
                        }
                    }
                }
            });
        }
    
    }
    
    私有最终类轮询器实现可运行{
    私有最终可调用轮询任务;
    轮询器(可调用轮询任务){
    this.pollingTask=pollingTask;
    }
    @凌驾
    公开募捐{
    AbstractPollingEndpoint.this.taskExecutor.execute(()->{
    整数计数=0;
    while(AbstractPollingEndpoint.this.initialized
    
    && (AbstractPollingEndpoint.this.maxMessagesPerPoll感谢@Artem,在您的回答后,我在上面的问题中添加了一个问题。在查看AbstractPollingEndpoint类后,这无疑增加了我的理解,但不确定我是否正确理解了该模式。是的,您的理解是正确的。您还可以考虑使用
    CallersRun策略
    适用于您的任务执行者,因此当池中没有线程时,调度程序的线程将执行轮询周期。但同时,在该线程空闲之前,不会启动更多新的轮询周期。感谢@Artem,在您的回答后,我在上面的问题中添加了一个问题。这无疑增加了我在查看后的理解AbstractPollingEndpoint类,但不确定我是否正确理解了该模式。是的,您的理解是正确的。您还可以考虑为任务执行器使用
    CallersRunPolicy
    ,因此当池中没有线程时,调度程序的线程将执行轮询周期。但同时,不会再启动新的轮询周期直到这个线程被释放。