【问题标题】:Spring JMS Connections: performance considerationsSpring JMS 连接:性能注意事项
【发布时间】:2012-02-15 02:38:09
【问题描述】:

我需要向/从存储在单个 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只能注册1个Listener,所以我不明白连接共享到什么程度。

假设我想注册 N 个 Listeners:我需要重复 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 一个或只是一个连接池?如果我为SimpleMessageListenerContainer-s 提供singleConnectionFactory 的引用呢?

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

【问题讨论】:

    标签: performance spring jms spring-jms


    【解决方案1】:

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

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

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

    JMS Connection 对象是线程安全的,可以被多个线程同时使用。所以不需要使用多个SingleConnectionFactory bean。

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

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

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

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

    【讨论】:

    • 嗨!谢谢回答!如果创建一个带有对 singleConnectionFactory 的引用的 SimpleMessageListenerContainer,我会收到以下异常:“在类路径资源 xxx 中定义名称为 'org.springframework.jms.listener.SimpleMessageListenerContainer#0' 的 bean 调用 init 方法失败;嵌套异常是 org .springframework.jms.IllegalStateException:共享连接的代理不支持 setExceptionListener 调用。改为在 SingleConnectionFactory 上设置 'exceptionListener' 属性。或者,......“你知道是否缺少某些东西吗?
    猜你喜欢
    • 2011-07-09
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 2017-06-15
    • 2013-06-04
    相关资源
    最近更新 更多