我有一个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>
答案 0 :(得分:1)
不确定你的意思是“间隔时间(消费者”询问“投票方式的消息,这很奇怪”。
容器线程可能“看起来”像是在轮询,但它们不是;它们在AMQ客户端中阻塞,直到消息到达或超时;当超时时,它会立即返回到AMQ receive()。
这个配置看起来很好;使用一个线程,消耗速率将直接取决于您在路由器下游所做的事情。
答案 1 :(得分:0)
建议使用PooledConnectionFactory。建议将其与Spring JmsTemplate一起使用,并将其池化为Connection,Session和MessageProducer实例,以便在它们不再使用后返回它们。
我相信您在消费者方面看到的“间隔”行为是消费者超时。
与Gary Russel所说的相反,amq.receive()
确实有效地轮询了队列。 Spring配置隐藏了这一点,但是消息是从队列中拉出来的,基本上是一个循环,在队列的使用者身上调用receive。队列的使用者无法知道消息是否在队列中,直到它调用receive()
来尝试获取消息。
这与主题相反,您可以在其中注册一个在消息进入时执行操作的侦听器。主题是一种优雅的解决方案,因为您注册了一个处理消息的侦听器。
使用主题,你告诉activemq如何处理消息,使用队列,activemq只会在你要求时给你消息。