Spring JMS Connections: соображения производительности - PullRequest
1 голос
/ 20 января 2012

У меня есть необходимость отправлять / получать сообщения на разные темы, хранящиеся на одном 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? Или они должны получать отдельный экземпляр каждый (singleConnectionFactory1, singleConnectionFactory2 и т. Д.)?

Читая API для SingleConnectionFactory, я нашел это:

Обратите внимание, что контейнеры приемника сообщений Spring поддерживают использование общего Connection в каждом экземпляре контейнера слушателя. Использование SingleConnectionFactory в комбинации действительно имеет смысл только для совместного использования одного JMS-соединения между несколькими контейнерами слушателя.

Это звучит немного загадочно для меня. Насколько я знаю, можно зарегистрировать только 1 прослушиватель на 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 или просто пул соединений? А что если я предоставлю SimpleMessageListenerContainer -ам ссылку на singleConnectionFactory?

Каков наилучший подход (с точки зрения спектаклей, конечно) в этом случае?

1 Ответ

6 голосов
/ 20 января 2012

если я создаю несколько jmsTemplate (s), могут ли они все поделиться ссылкой на singleConnectionFactory?

Да, это нормально. Javadoc для SingleConnectionFactory говорит:

В соответствии с моделью JMS Connection, это абсолютно потокобезопасно (в отличие, например, от JDBC).

Объекты JMS Connection являются поточно-ориентированными и могут использоваться несколькими потоками одновременно. Поэтому нет необходимости использовать несколько SingleConnectionFactory bean-компонентов.

Насколько я знаю, можно зарегистрировать только 1 прослушиватель на MessageListenerContainer, поэтому я не понимаю, в какой степени соединение является общим.

Это правда; однако каждый MessageListenerContainer может иметь несколько потоков, обрабатывающих сообщения одновременно, причем все используют один и тот же объект MessageListener. MessageListenerContainer будет использовать один общий Connection для всех этих потоков (если не настроено иное).

Обратите внимание, что контейнеры приемника сообщений Spring поддерживают использование общего соединения в каждом экземпляре контейнера приемника. Использование SingleConnectionFactory в комбинации имеет смысл только для совместного использования одного JMS-соединения между несколькими контейнерами слушателя.

Другими словами, если все, что у вас есть, это один MessageListenerContainer, то SingleConnectionFactory не требуется, поскольку внутреннее управление одиночным соединением осуществляется до MessageListenerContainer. если у вас есть несколько контейнеров слушателей, и вы хотите, чтобы все они совместно использовали соединение, то SingleConnectionFactory требуется. Кроме того, если вы хотите разделить соединение между прослушиванием и отправкой, как вы делаете, тогда SingleConnectionFactory также необходимо.

...