Ответ 1
Единственное, что вам нужно создать снова и снова, это сам msg
- если вы отправляете в ту же очередь.
Итак, вы можете вспомнить Connection, Session и Sender.
У меня возникли проблемы с пониманием 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);
}
Код верный, но, вероятно, некоторые из вышеперечисленных артефактов могут быть повторно использованы для нескольких сообщений. Это наши конфигурации:
QueueConnection
, QueueSession
, QueueSender
) в памяти, так как нет concurrency.Единственное, что вам нужно создать снова и снова, это сам msg
- если вы отправляете в ту же очередь.
Итак, вы можете вспомнить Connection, Session и Sender.
Вот некоторые важные части jms spec:
раздел 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 и Destinations для всех потоков. Для каждой темы повторное использование потребителей и производителей.
Если вы повторно используете JMS-подключение, будьте осторожны, что JMS Provider будет мультиплексировать разные сеансы в этих соединениях. Поэтому, даже если безопасно повторно использовать соединения, возможно, быстрее создать соединение для каждого сеанса, который вам нужен.
Определите, "поделиться" .
Если вы хотите поделиться между разными потоками, это очень опасно. Вы можете безопасно обмениваться объектом QueueConnectionFactory, а также объектом JMS Connection. Вы не должны совместно использовать объекты Session, Sender/Consumer или Message. То, как работает TIBCO EMS, я не уверен в платформе IBM, но я думаю, что это очень похоже.
Если вы можете быть уверены, что ваш метод отправки не вызывается разными потоками, вы можете его инкапсулировать в класс 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.