Spring JMS Connections:性能考虑因素

时间:2012-01-20 14:34:04

标签: performance spring jms spring-jms

我需要向存储在单个JMS服务器上的不同主题发送/接收消息。

我想使用JmsTemplate发送和MessageListenerContainer来注册异步侦听器。

我的配置如下:

<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
        <props>
            <prop key="java.naming.factory.initial">xxx</prop>
            <prop key="java.naming.provider.url">yyy</prop>
        </props>
    </property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate" ref ="jndiTemplate"/>
        <property name="jndiName" value="TopicConnectionFactory"/>
    </bean>

    <bean id="singleConnectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
        <constructor-arg ref="connectionFactory"/>
    </bean>

    <bean id="tosJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="singleConnectionFactory"/>
        <property name="destinationResolver" ref="destinationResolver"/>
        <property name="pubSubDomain" value="true"/>
    </bean>

据我所知,singleConnectionFactory总是返回相同的连接实例,有助于减少创建和关闭的开销 每次jmsTemplate需要(例如)发送/接收消息时的连接(就像使用普通ConnectionFactory时那样)。

我的第一个问题是:如果我创建多个jmsTemplate(s),他们是否可以共享singleConnectionFactory的引用?或者他们必须分别收到一个不同的实例(singleConnectionFactory1singleConnectionFactory2等)?

阅读SingleConnectionFactory的API,我发现了这个:

  

请注意,Spring的消息侦听器容器支持使用共享Connection   在每个侦听器容器实例中。结合使用SingleConnectionFactory只对跨多个侦听器容器共享单个JMS连接非常有意义。

这听起来对我来说有点神秘。据我所知,每MessageListenerContainer只能注册一个监听器,所以我不明白连接的共享程度。

假设我要注册N个监听器:我需要重复N次这样的事情:

<bean 
    class="org.springframework.jms.listener.SimpleMessageListenerContainer"> 
    <property name="connectionFactory" ref="connectionFactory" /> 
    <property name="destinationName" value="destX" /> 
    <property name="messageListener" ref="listener1outOfN" /> 
</bean> 

在这种情况下,connectionFactory创建了多少个连接?每个ListenerContainer一个或只是一个Connections池?如果我向SimpleMessageListenerContainer - s提供引用singleConnectionFactory,该怎么办?

在这种情况下,最好的方法是什么(当然,从表演的角度来看)?

1 个答案:

答案 0 :(得分:6)

  

如果我创建多个jmsTemplate(s),它们是否可以共享一个singleConnectionFactory的引用?

是的,这很好。 SingleConnectionFactory的javadoc说:

  

根据JMS Connection模型,这是完全线程安全的(与例如JDBC相反)。

JMS Connection对象是线程安全的,并且可以由多个线程同时使用。因此,不需要使用多个SingleConnectionFactory bean。

  

据我所知,每MessageListenerContainer只能注册一个监听器,所以我不明白连接的共享程度。

这是真的;但是,每个MessageListenerContainer可以有多个线程同时处理消息,所有这些线程都使用相同的MessageListener对象。 MessageListenerContainer将为所有这些线程使用单个共享Connection(除非另有配置)。

  

请注意,Spring的消息侦听器容器支持在每个侦听器容器实例中使用共享Connection。结合使用SingleConnectionFactory只对跨多个侦听器容器共享单个JMS连接非常有意义。

换句话说,如果您只拥有一个MessageListenerContainer,则SingleConnectionFactory是不必要的,因为单个连接在内部管理到MessageListenerContainer。如果您有多个侦听器容器,并希望它们全部共享连接,则需要SingleConnectionFactory。此外,如果您想像在一样共享收听和发送之间的连接,那么SingleConnectionFactory也是必要的。