简体   繁体   English

Spring集成

[英]Spring Integration

Our application has been designed using Spring Integration Framework. 我们的应用程序是使用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. 完整的消息操作流程开始于侦听已使用JMS消息驱动适配器的Queue,之后已定义基于通道的队列端点,并且每个端点都由Service-Activators处理。

We are currently into performance phase, we are spawning 200 message request. 我们目前正处于性能阶段,我们正在产生200条消息请求。 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. 最初我们观察到消息没有并行执行,在做了一些阅读后发现通过将并发消费者和最大并发消费者属性添加到JMS消息驱动的侦听器适配器将有助于启用多线程模式。 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. 您认为通过向每个Channel端点定义添加队列容量将再次有助于在多线程模式下运行。

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. 默认情况下,Spring通道在发送方的线程中使用其消息。 In other words, it's synchronous. 换句话说,它是同步的。 If you want a channel to consume messages asynchronously, you'll have to specify a TaskExecutor. 如果您希望通道异步使用消息,则必须指定TaskExecutor。 See http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/scheduling.html 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 . 要从消息驱动的通道适配器(您尚未显示配置)开始,可以将其配置为具有多于1个默认使用者 ,并且可以使每个使用周期消耗合理数量的消息

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. 通过消息驱动的通道适配器,将消息放入直接通道1的线程将遗憾地运行其余的流程,因为其他地方没有缓冲,因此当您的消息被放入“直接通道1”时,它将立即调用同一线程中的路由器,然后在同一个线程中调用服务激活器和邮件适配器或JMS出站通道适配器。 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. 这里的改变可能是引入队列通道而不是直接通道1 ,这样消耗消息的线程就将消息放入队列通道然后用它来完成。

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 超越直接通道1(更改为队列通道1),我认为可以根据流量的快慢来实现单线程, 如果邮件适配器速度慢,则直接通道4也可以成为队列通道 ,同样直接通道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. 为了提高性能,我建议使用带有任务执行器的executorchannel来控制线程池大小的数量。 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. 通过这种方式,您可以获得消息到达jms队列时消费者接收消息并在单独的线程中处理流的情况。 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. 请记住,在这种配置中,多线程工作由taskexecutor通道执行,taht将在单独的线程中执行消息的重传,因此您已经想到了您想要的多线程等级。

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. 对于队列消息通道,确实需要轮询器在通道上轮询执行recive,队列容量是幕后原子队列的容量。

you can configure am executor channel in this way in xml 您可以在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 或者以这种方式在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)))
                .....

        }

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

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