如何在Spring Integration中处理繁重的消息加载?

时间:2013-11-14 08:31:10

标签: spring messaging spring-integration

外部模块向消息代理发送数千条消息。每条消息的TimeToLive属性等于5秒。另一个模块应该使用和处理所有消息。

从Spring Integration文档中我发现了分阶段事件驱动 架构(消费者)对负载中的重大峰值做出更好的响应。

我目前的实施使用EDA(甚至是驱动架构),例如

<si:channel id="inputChannel"/>

<!-- get messages from PRESENCE_ENGINE queue -->    
<int-jms:message-driven-channel-adapter id="messageDrivenAdapter" 
    channel="inputChannel" destination="sso" connection-factory="connectionFactory"  
    max-concurrent-consumers="1" auto-startup="true" acknowledge="transacted" extract-payload="true"/>

<si:service-activator id ="activatorClient" input-channel="inputChannel" ref="messageService" method="processMessage"/> 

<bean id="messageService" class="com.my.messaging.MessageService"/>

<bean id="sso" 
    class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="SSO" />
</bean> 

显然是在重载下,例如。传入数千条消息,processMessage()可能需要超过5秒。并且MessageService可能无法处理所有消息。

我的想法如下:

  1. 修改processMessage()以使消息代替 processed只存储在MongoDB中。然后我就可以处理了 单独任务中的消息。在这种情况下 MongoDB将充当CACHE。

  2. 使用大量消费者(SEDA模型)。 inputChannel是一个直接通道。

  3. 异步处理消息,例如inputChannel是队列通道,并且异步处理消息。
  4. 在做出决定之前,我想问你哪种情况更有效。也许方案2)和3)提供了一种机制来满足我的要求,即所有消息都应该被处理,即使是重负荷也是如此。

    修改

    我已经实现了方案2,我每秒都会发送1000条消息。 这是统计有多少消息丢失的参数:

    max-concurrent-consumers;传输TimeToLive = 5secs .;空闲消费限制;发送的消息数量;收到的消息数

     10 ; Yes ; 1   ; 1001 ; 297
    100 ; Yes ; 1   ; 1001 ; 861
    150 ; Yes ; 1   ; 1001 ; 859
    300 ; Yes ; 1   ; 1001 ; 861
    300 ; No  ; 1   ; 1001 ; 860
    300 ; No  ; 100 ; 1001 ; 1014
    300 ; No  ; 50  ; 1001 ; 1011
    

    似乎闲置 - 消费者限制比最大并发消费者更具侵略性地创造消费者。在这种情况下,这是一种使用idle-consumer-limit的好方法吗?

    这是发件人/消费者的配置文件:

    <!-- SENDER  
    Keep Alive Sender sends messages to backup server -->    
    
    <si:channel id="sendToChannel"/>
    <si:channel id="presChannel"/>
    
    <si:inbound-channel-adapter id="senderEntity" channel="sendToChannel" method="sendMessage"> 
        <bean class="com.ucware.ucpo.sso.cache.CacheSender"/>
        <si:poller fixed-rate="${sender.sendinterval}"></si:poller>
    </si:inbound-channel-adapter>    
    
    <si:router id="messageRouter" method="routeMessage" input-channel="sendToChannel">
        <bean class="com.ucware.ucpo.sso.messaging.MessageRouter"/>
    </si:router>
    
    <!-- Subscriber to a channel dispatcher, Send messages to JMS -->
    <int-jms:outbound-channel-adapter  explicit-qos-enabled="${jms.qos.enabled}" time-to-live="${jms.message.lifetime}" 
        channel="presChannel" connection-factory="connectionFactory" destination="pres" extract-payload="false"/>
    
    <bean id="pres" 
        class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="PRES" />
    </bean>
    
    
    <!-- RECEIVER -->
    
    <si:channel id="receiveChannel"/>
    
    <!-- get messages from PRES queue -->    
    <int-jms:message-driven-channel-adapter id="messageDrivenAdapter" 
        channel="receiveChannel" destination="presence" connection-factory="connectionFactory"  idle-consumer-limit="50" 
        max-concurrent-consumers="300" auto-startup="true" acknowledge="transacted" extract-payload="true"/>
    
    <si:service-activator id ="activatorClient" input-channel="receiveChannel" ref="messageService" method="processMessage"/> 
    
    
    <bean id="messageService" class="com.cache.MessageService"/>
    

1 个答案:

答案 0 :(得分:3)

首先,您可以尝试使用max-concurrent-consumers属性。如您所见,在您的情况下1实在是不够。 您应该调查MessageService为什么这么慢的原因。 任何其他情况看起来都是开销,因为JMS已经是持久的并且具有异步性质 - 基于队列。 如果它没有帮助,那么请使用<queue>频道与precestence MessageStore,例如MongoDB的