jms和spring集成的性能问题。以下配置有什么问题?

时间:2012-11-21 14:06:50

标签: jms activemq messaging spring-integration

我有一个jms生成器,它每秒生成许多消息,它们被发送到amq持久队列并被单个消费者使用,需要按顺序处理它们。但似乎生产者比消费者快得多,而且我有性能和内存问题。消息的获取非常缓慢,消费似乎是间隔发生的(消费者以轮询方式“询问”消息,这很奇怪?!)

基本上一切都发生在Spring集成中。这是生产者方面的配置。第一个赌注消息来自stakesInMemoryChannel,从那里,他们被过滤抛出filteredStakesChannel并从那里进入jms队列(使用执行器,因此发送将在单独的线程中发生)

    <bean id="stakesQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg name="name" value="${jms.stakes.queue.name}" />
    </bean>

    <int:channel id="stakesInMemoryChannel" />

    <int:channel id="filteredStakesChannel" >
        <int:dispatcher task-executor="taskExecutor"/>
    </int:channel>

    <bean id="stakeFilterService" class="cayetano.games.stake.StakeFilterService"/>

    <int:filter 
       input-channel="stakesInMemoryChannel"
       output-channel="filteredStakesChannel" 
       throw-exception-on-rejection="false"
       expression="true"/>

    <jms:outbound-channel-adapter channel="filteredStakesChannel" destination="stakesQueue" delivery-persistent="true" explicit-qos-enabled="true"  />

    <task:executor id="taskExecutor" pool-size="100" />

另一个应用程序正在使用这样的消息......消息来自jms stakesQueue的stakesInputChannel,之后它们被路由到两个独立的通道,一个持久化消息而另一个做其他一些东西,让我们调用它“处理”。

    <bean id="stakesQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg name="name" value="${jms.stakes.queue.name}" />
</bean>

<jms:message-driven-channel-adapter 
    channel="stakesInputChannel" 
    destination="stakesQueue" 
    acknowledge="auto"
    concurrent-consumers="1"
    max-concurrent-consumers="1"
    />
<int:publish-subscribe-channel id="stakesInputChannel" />
<int:channel id="persistStakesChannel" />
<int:channel id="processStakesChannel" />

<int:recipient-list-router 
        id="customRouter" 
        input-channel="stakesInputChannel" 
        timeout="3000" 
        ignore-send-failures="true" 
        apply-sequence="true"
        >
    <int:recipient channel="persistStakesChannel"/>
    <int:recipient channel="processStakesChannel"/>
</int:recipient-list-router> 


<bean id="prefetchPolicy" class="org.apache.activemq.ActiveMQPrefetchPolicy">
    <property name="queuePrefetch" value="${jms.broker.prefetch.policy}" />
</bean>

<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="targetConnectionFactory">
        <bean class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL" value="${jms.broker.url}" />     
            <property name="prefetchPolicy" ref="prefetchPolicy" /> 
            <property name="optimizeAcknowledge" value="true" /> 
            <property name="useAsyncSend" value="true" />
        </bean>
    </property>
    <property name="sessionCacheSize" value="10"/>
    <property name="cacheProducers" value="false"/>
</bean>

2 个答案:

答案 0 :(得分:1)

不确定你的意思是“间隔时间(消费者”询问“投票方式的消息,这很奇怪”。

容器线程可能“看起来”像是在轮询,但它们不是;它们在AMQ客户端中阻塞,直到消息到达或超时;当超时时,它会立即返回到AMQ receive()。

这个配置看起来很好;使用一个线程,消耗速率将直接取决于您在路由器下游所做的事情。

答案 1 :(得分:0)

建议使用PooledConnectionFactory。建议将其与Spring JmsTemplate一起使用,并将其池化为Connection,Session和MessageProducer实例,以便在它们不再使用后返回它们。

我相信您在消费者方面看到的“间隔”行为是消费者超时。

与Gary Russel所说的相反,amq.receive()确实有效地轮询了队列。 Spring配置隐藏了这一点,但是消息是从队列中拉出来的,基本上是一个循环,在队列的使用者身上调用receive。队列的使用者无法知道消息是否在队列中,直到它调用receive()来尝试获取消息。

这与主题相反,您可以在其中注册一个在消息进入时执行操作的侦听器。主题是一种优雅的解决方案,因为您注册了一个处理消息的侦听器。

使用主题,你告诉activemq如何处理消息,使用队列,activemq只会在你要求时给你消息。