我在从性能角度理解 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
)保留在内存中会很简单,因为不涉及并发。以下是 jms 规范的一些相关部分:
2.8 节多线程
JMS Object Supports Concurrent Use
Destination YES
ConnectionFactory YES
Connection YES (as of jakarta messaging 3.0 with some restrictions, see [jakarta messaging 3.0 spec][2])
Session NO
MessageProducer NO
MessageConsumer NO
第 4.4.14 节客户端代码的串行执行
JMS 不会导致客户端代码并发执行,除非客户端明确请求。完成此操作的一种方法是定义会话序列化所有异步消息传递
正如已经提到的,尽可能地重复使用。为所有线程重用 ConnectionFactory、Connection 和 Destinations。对于每个线程重用消费者和生产者。
如果您重用 JMS 连接,请注意,JMS 提供程序将在该连接上复用不同的会话。因此,即使重用连接是安全的,为您需要的每个会话创建连接可能会更快。
您唯一需要一次又一次创建的是
msg
本身 - 如果您要发送到同一个队列。
所以,是的,您可以记住连接、会话和发件人。
定义“分享”。
如果您打算在不同线程之间共享,这是非常危险的。您可以安全地共享 QueueConnectionFactory 对象以及 JMS Connection 对象。您不得共享会话、发送者/消费者或消息对象。这就是 TIBCO EMS 的工作方式,我不确定 IBM 平台,但我想这是非常相同的。
如果您可以确定您的“发送”方法不会被不同的线程调用,您可以将其封装到具有 Connection、Session 和 Sender 成员变量的 MySender 类中。但要小心!请在退出时正确关闭资源。这就是 Heiko Rupp 的建议。像这样的事情:
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。