jms 生产者性能与春天

Posted

技术标签:

【中文标题】jms 生产者性能与春天【英文标题】:jms producer performance with spring 【发布时间】:2011-10-26 17:47:17 【问题描述】:

我基于spring、jms和activemq创建了一个简单的生产者消费者模拟, 我正在尝试从生产者和消费者双方都获得高性能,

连接设置:

<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
     <property name="connectionFactory"  ref="connectionFactory" />
</bean>

<amq:connectionFactory id="amqConnectionFactory" brokerURL="failover:(tcp://$broker.url:61616)"  />

<bean id="connectionFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="targetConnectionFactory" ref="amqConnectionFactory" />
</bean>

<amq:queue id="queue" physicalName="queue" />

<beans:bean id="jsonMessageConverter" class="XXXXX.converter.JsonMessageConverter" />

消费者设置:

<jms:listener-container concurrency="10"
    acknowledge="auto" prefetch="1" message-converter="jsonMessageConverter" transaction-manager="transactionManager"

    >
    <jms:listener id="queueListener_1" destination="ooIntegrationQueue"
        ref="myMessageListenerAdapter" />
</jms:listener-container>


<beans:bean id="myMessageListenerAdapter"
    class="org.springframework.jms.listener.adapter.MessageListenerAdapter" >
    <beans:property name="delegate" ref="consumer"/>
</beans:bean>


<beans:bean id="consumer" class="XXX.ConsumerImpl"/>

生产者设置:

<beans:bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
    p:connectionFactory-ref="connectionFactory" p:messageConverter-ref="jsonMessageConverter"
    p:defaultDestination-ref="ooIntegrationQueue" p:sessionTransacted="true" />

从消费者开始,我设法每秒消耗大约 25 条消息,这非常慢,我发现瓶颈在于我正在使用事务, 在谷歌搜索了一下并使用配置后,我发现在自动装配 DefaultMessageListenerContainer 并将缓存级别更改为

listenerContainer.setCacheLevelName("CACHE_SESSION") 

我的性能提高到每秒大约 1500 条消息,同时仍然有事务。

我现在的问题是生产者仍然卡在每秒大约 25 次操作, 我的生产者测试很简单:

int numOfMessages = getNumberOfMessages();


double startTime = System.currentTimeMillis();

for (int i = 1; i <= numOfMessages; i++) 
    jmsTemplate.convertAndSend("HelloWorld" + i);


double endTime = System.currentTimeMillis();

double totalTime=(endTime-startTime)/1000;
System.out.println("Time - "+totalTime+" seconds");
System.out.println("EPS - "+numOfMessages/totalTime);

我想知道如何与制作人达到类似的性能,因为它现在成为整个系统的瓶颈。

【问题讨论】:

【参考方案1】:

ActiveMQ 的默认交付模式是什么?它是一个持久队列吗?如果是这样,它是如何配置的?经纪人有多远?这些答案将通过回答服务器确认发送需要多长时间来确定发送到队列的基本成本(即网络 RTT + 将消息同步持久化到磁盘的潜在成本)。

另一种可能性是,您实际上是在每次发送时创建一个新的连接、会话和消息生产者。至少可以说这是相当昂贵的。值得确认这是否正在发生(例如,将调试日志添加到 spring,检查 amq 管理控制台的连接流失)或不作为基本的健全性检查。从外观上看,CachingConnectionFactory 应该默认缓存单个会话和消息生产者,convertAndSend 应该在发送后关闭它获得的会话,这会导致将该缓存的会话返回到池中。这应该意味着在下一次发送时获取缓存会话相对较快(spring jms 通过大量代码只是为了发送消息)。

【讨论】:

目前消息不是持久的,我调试了 jmsTemplate 并且缓存了会话和生产者,我决定尝试一个没有 spring 的基本示例,结果证明(这是有道理的)提交每条消息的会话会产生相同的性能,只是批量处理一定数量的消息然后提交事务会给我想要的结果。 如果一个普通的 vanilla 测试和一个基于 spring 的测试具有相同的性能,那么你可以很确定的瓶颈在经纪人身上。 25/s 相当于每条消息 40ms。这可能是相当合理的,具体取决于代理的确认方式(以及发送是否异步)以及它处理消息的方式以及它运行的硬件。什么是默认交付模式?我的猜测是PERSISTENT,如果是这样尝试切换到NON_PERSISTENT,您应该会看到吞吐量上升。如果还没有默认使用异步发送,您还应该考虑使用它。【参考方案2】:

JMSTemplate 执行 ConnectionFactiory -> Connection -> Session -> MessageProducer,每次发送后关闭每个对象。为了解决这个问题,使用 org.apache.activemq.pool.PooledConnectionFactory 包装您的 amqConnectionFactory bean,并在模板下使用它而不是 CachingConnectionFactory。

【讨论】:

已经尝试过了,CachingConnectionFactory 默认池大小为 1,更改该值不会有太大变化,同样使用 PooledConnectionFactory(默认池大小为 500)也可以提供类似的性能 那里肯定有什么东西在运行 - 在测试本身上粘贴一个分析器,看看您是否可以识别热点。出于好奇,当您将转换器排除在外时,性能如何? IE。发送简单的测试消息。另一件事是,您正在单线程中测试线性性能;这可能不是现场使用的方式。一个更有用的测试是通过将 convertAndSend 调用包装在 Runnable 中并将其传递给 ExecutorService 来使水平负载饱和。 投反对票,真的吗?我没有看到您对马特回答的回复,但我认为这是一个合理的问题。我认为您的生产者代码在 JUnit 测试中,尽管那里没有足够的信息。使用类似的配置,我每秒看到 1000 条消息。 +1'ed 因为这通常是一个正确的答案,尽管它似乎对 James T 的具体情况没有帮助。我们还不知道 JsonMessageConverter 的成本有多高,并且该测试设置为在生产者端以同步方式执行操作,因此 JsonMessageConverter 实际上可能是瓶颈。【参考方案3】:

尝试将确认方法从 AUTO 更改为 CLIENT_ACKNOWLEDGE。更多信息请查看Specification。

【讨论】:

【参考方案4】:

对不起,如果这个答案来晚了以帮助原始海报。我最近调查了JmsTemplate 的性能。即使使用相同的交付和确认模式,本机 JMS 代码似乎也比 JmsTemplate 快​​得多。问题原来是ActiveMQ 通常默认为异步发送,但是当您使用JmsTemplate 时,它改为使用同步发送。这会大大降低性能。您可以将ActiveMQConnectionFactoryuseAsyncSend 属性设置为true 以强制异步发送。更多细节在这里:JmsTemplate is not evil

【讨论】:

以上是关于jms 生产者性能与春天的主要内容,如果未能解决你的问题,请参考以下文章

WSO2 ESB 5.0.0 配置 JMS 传输(ActiveMQ)- 队列消息生产与消费

WSO2 ESB 5.0.0 配置 JMS 传输(ActiveMQ)- 队列消息生产与消费

WSO2 ESB 5.0.0 配置 JMS 传输(ActiveMQ)- 队列消息生产与消费

JMS与ActiveMQ

JMS基础知识

JMS(Java消息服务)认识与学习