Производительность JMS - PullRequest
20 голосов
/ 29 марта 2011

У меня проблемы с пониманием JMS с точки зрения производительности. У нас в приложении очень простой код:

QueueConnection connection = null;
QueueSession session = null;
QueueSender sender = null;
TextMessage msg = null;

try {
  // The JNDIHelper uses InitialContext to look up things
  QueueConnectionFactory qcf = JNDIHelper.lookupFactory();
  Queue destQueue = JNDIHelper.lookupQueue();

  // These objects are created for every message, which is quite slow
  connection = qcf.createQueueConnection();
  session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
  sender = session.createSender(destQueue);

  // This is the actual message
  msg = session.createTextMessage(xmlMsg);
  sender.setTimeToLive(0);
  sender.send(msg);
} 
finally {

  // Close all objects again
  JMSUtilities.safeClose(sender);
  JMSUtilities.safeClose(session);
  JMSUtilities.safeClose(connection);
}

Код правильный, но, возможно, некоторые из вышеперечисленных артефактов могут быть повторно использованы для нескольких сообщений. Вот наши конфигурации:

  • Мы используем Oracle Weblogic 10.3.3
  • Weblogic подключается к IBM MQ 7.0 (проблема также появляется с 6.0) для JMS
  • Вышеприведенная логика выполняется одним потоком на внутреннем сервере. Было бы просто сохранить некоторые объекты (QueueConnection, QueueSession, QueueSender) в памяти, так как в них нет параллелизма.

Мои вопросы

  • Какие типы объектов могут быть общими для нескольких сообщений? (конечно, мы включили бы восстановление после ошибок, восстановление этих общих объектов)
  • Каковы лучшие практики для повышения производительности?

Ответы [ 3 ]

16 голосов
/ 05 сентября 2013

Вот некоторые важные части спецификации jms :

раздел 2.8 Многопоточность

JMS Object          Supports Concurrent Use
Destination         YES
ConnectionFactory   YES
Connection          YES
Session             NO
MessageProducer     NO
MessageConsumer     NO

раздел 4.4.14 Последовательное выполнение кода клиента

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

Так как уже упоминалось, используйте как можно больше. Повторно используйте ConnectionFactory, Connection и Destination для всех потоков. Для каждого потока повторно использовать потребителей и производителей.

Если вы повторно используете соединение JMS, остерегайтесь, что провайдер JMS будет мультиплексировать различные сеансы на этих соединениях. Поэтому, даже если безопасно повторно использовать соединения, может быть быстрее создать соединение для каждого сеанса, который вам нужен.

10 голосов
/ 29 марта 2011

Единственное, что вам нужно создать снова и снова, это сам msg - если вы отправляете в одну и ту же очередь.

Так что да, вы можете вспомнить Соединение, Сеанс и Отправитель.

3 голосов
/ 29 марта 2011

Определите "поделиться" .

Если вы хотите поделиться между различными потоками , это очень опасно.Вы можете безопасно поделиться объектом QueueConnectionFactory, а также объектом JMS-соединения.Вы не должны предоставлять общий доступ к объектам Session, Sender / Consumer или Message.Вот как работает TIBCO EMS. Я не уверен насчет платформы IBM, но думаю, что она очень похожа.

Если вы можете быть уверены, что ваш метод send не вызывается из разных потоков Вы можете инкапсулировать это в класс MySender с помощью переменных-членов Connection, Session и Sender.Но будь осторожен!Правильно закройте ресурсы при выходе.Вот что рекомендует Хайко Рупп.Что-то вроде этого:

class MySender {
    private QueueConnection connection = null;
    private QueueSession session = null;
    private QueueSender sender = null;

    public MySender(...) { /* initialize conn/sess/sender */ }

    public send(String xmlMsg) { /* sender.send(session.createTextMessage(xmlMsg)) */ }

    public close() { /* close all resources */ }
}

Относительно производительности.В стандарте JMS нет места для улучшения.Держите сообщения небольшими и оптимизируйте настройки сервера.Используйте долгосрочные пункты назначения только тогда, когда вам это нужно и т. Д. Прочитайте документацию для вашей платформы.Но на стороне клиента не так много места.На некоторых платформах JMS предлагает дополнительные функции, которые позволяют повысить производительность (пакетные отправки и т. Д.), Но это зависит от платформы.Я не знаю IBM.

...