简体   繁体   中英

Spring Integration

Our application has been designed using Spring Integration Framework. Complete message action flow starts with listening to Queue's for which JMS message driven adapters has been used after which channel based ie queue endpoints have been defined and each endpoint is processed by Service-Activators.

We are currently into performance phase, we are spawning 200 message request. Initially we observed that messages were not executing in parallel, after doing some reading figured out that by adding concurrent-consumer and max-concurrent-consumer property to JMS message driven listener adapter will help to enable multi-threading mode. Indeed this helped but still somewhere in between the process I still see Single Thread effect. Is this due to way the endpoint has been defined? What is the advantage of adding Queue capacity to each endpoint? Do you think by adding queue-capacity to each Channel endpoint definition will again help to run in mutli-threading mode.

The design snapshot as requested:

行动流程

It would be helpful to see the exact definition of your channels.

By default, a Spring channel consumes its message in the sender's thread. In other words, it's synchronous. If you want a channel to consume messages asynchronously, you'll have to specify a TaskExecutor. See http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/scheduling.html

Looking at your flow diagram, it looks like the flow has a lot of single threaded elements and can be optimized to be much more concurrent with hopefully higher throughput.

To start with the message driven channel adapter (you have not shown the configuration for that), can be configured to have more than 1 default consumer , and can be made to consume a reasonable number of message per consume cycle .

Past the message driven channel adapter, the thread which puts the message into the direct channel 1, will unfortunately run the rest of the flow as there is no buffering anywhere else, so when your message is put into "Direct Channel 1", it will immediately invoke the router in the same thread then invoke the service activator and the the Mail adapter or JMS Outbound channel adapter in the same thread. The change here could be to introduce a queue channel instead of direct channel 1 , this way the thread which is consuming the message just places the messages in the queue channel is then done with it.

Beyond Direct channel 1(changed to Queue Channel 1), it I think can be single threaded based on how fast or slow your flow is, if say the mail adapter is slow then Direct Channel 4 can be made a queue channel also , same with Direct Channel 5

Can you please see if these changes highlighted in bold help with making the flow better

For increas performance I can suggest of use a executorchannel with a task executor in wich control the number of the thread pool size. In this way you have the situation in which when a message arrives in the jms queue the consumer take the message and in a separate thread process the flow. remember that in this kind of configuration the multithreadng work is performed by the taskexecutor channel taht will perform the recive of the message in a separate thread for this reason you have think well what grade of multithreading you want.

For the queue message channel indeed you need of a poller that polling on the channel for perform the recive, the queue capacity is the capacity of the atomic queue behind the scenes.

you can configure am executor channel in this way in xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:si="http://www.springframework.org/schema/integration"
       xmlns:tx="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/integration 
        http://www.springframework.org/schema/integration/spring-integration.xsd 
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">

       <tx:executor id="taskExecutor" pool-size="10" queue-capacity="10"/>
       <si:channel id="ch" >
              <si:dispatcher task-executor="taskExecutor"/>       
       </si:channel>
</beans>

or in this way in java-dsl

 @Bean
    public IntegrationFlow storeBookPageByPage(ConnectionFactory connectionFactory,
                                               @Qualifier("createBookQueue") Destination createBookQueue,
                                               @Qualifier("createBookResultQueue") Destination createBookResultQueue,
                                               PdfBookMasterRepository pdfBookMasterRepository,
                                               BookRepository bookRepository){
        String tempFilePathBaseDir = environment.getProperty("bookService.storeBookPageByPage.tempFilePathBaseDir");

        return IntegrationFlows.from(Jms.messageDriverChannelAdapter(connectionFactory)
                .destination(createBookQueue)
                .errorChannel(storeBookPageByPageErrorChannel()))
                .channel(channels -> channels.executor(Executors.newScheduledThreadPool(5)))
                .....

        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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