JMS 性能

问题描述 投票:0回答:3

我在从性能角度理解 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
    )保留在内存中会很简单,因为不涉及并发。

我的问题

  • 哪些类型的对象可以在多个消息之间共享? (当然我们会包括错误恢复,恢复那些共享对象)
  • 提高绩效的最佳实践是什么?
java jms weblogic message-queue
3个回答
16
投票

以下是 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 提供程序将在该连接上复用不同的会话。因此,即使重用连接是安全的,为您需要的每个会话创建连接可能会更快。


10
投票

您唯一需要一次又一次创建的是

msg
本身 - 如果您要发送到同一个队列。

所以,是的,您可以记住连接、会话和发件人。


3
投票

定义“分享”

如果您打算在不同线程之间共享,这是非常危险的。您可以安全地共享 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。

© www.soinside.com 2019 - 2024. All rights reserved.