Java JMS性能

Java JMS性能,java,jms,weblogic,message-queue,Java,Jms,Weblogic,Message Queue,我在从性能角度理解JMS时遇到了一些问题。我们的应用程序中有以下非常简单的代码: QueueConnection connection = null; QueueSession session = null; QueueSender sender = null; TextMessage msg = null; try { // The JNDIHelper uses InitialContext to look up things QueueConnectionFactory qcf

我在从性能角度理解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为JMS连接到IBM MQ 7.0(6.0也出现问题)
  • 上述逻辑由后端服务器上的单个线程执行。将一些对象(
    QueueConnection
    QueueSession
    QueueSender
    )保留在内存中很简单,因为不涉及并发性
我的问题
  • 哪些类型的对象可以在多条消息中共享?(当然,我们会包括错误恢复,恢复那些共享对象)
  • 提高绩效的最佳实践是什么

如果要发送到同一队列,则只需反复创建
msg
本身

因此,您可以记住连接、会话和发件人。

定义“共享”

如果你想在不同的线程之间共享,这是非常危险的。您可以安全地共享QueueConnectionFactory对象以及JMS连接对象。不得共享会话、发件人/消费者或邮件对象。这就是TIBCO EMS的工作方式我不确定IBM平台,但我想这是非常相同的

如果您可以确保“send”方法没有被不同的线程调用,那么您可以使用Connection、Session和Sender成员变量将其封装到MySender类中。但是要小心!请在退出时正确关闭资源。这就是海科·鲁普的建议。像这样的事情:

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。

以下是该系统的一些相关部分:

第2.8节多线程

JMS Object          Supports Concurrent Use
Destination         YES
ConnectionFactory   YES
Connection          YES
Session             NO
MessageProducer     NO
MessageConsumer     NO
第4.4.14节客户代码的串行执行

除非客户机明确请求,否则JMS不会导致客户机代码的并发执行。一种方法是定义会话序列化所有异步消息传递

因此,正如前面提到的,尽可能地重复使用。重用所有线程的ConnectionFactory、连接和目标。对于每个线程,重用使用者和生产者


如果要重用JMS连接,请注意JMS提供程序将在该连接上多路传输不同的会话。因此,即使重复使用连接是安全的,为您需要的每个会话创建连接可能会更快。

是的,队列总是相同的。因此,在保持会话活动时没有缺点?当然,如果他们断开连接,
连接
会话
,和
发送方
,我们会有故障转移逻辑恢复它们……如果连接或会话在某一点失败怎么办?我们需要再次创建连接吗?@Izap:查看我的配置部分:上面的逻辑由后端服务器上的单个线程执行。我不确定你关于客户端无法优化的一般假设是否正确。毕竟,这些资源是由Weblogic服务器与MQ合作分配和管理的……说您不应该共享JMS连接对象是错误的,从。。。连接支持并发use@Matt,Izap区分不应该和不应该,这是有意义的,因为
会话
是单线程对象,而
连接
不是。我不知道为什么我不应该这样做,但这对TIBCO来说并不一定是错误的,是吗?@Matt:JMS规范没有提到任何关于线程安全的内容。这取决于实施情况。但对于关系,你是对的。您可以共享它。@lzap:是的,可以,请参阅规范中关于多线程的第2.8节。我对finally块中的JMSUtilities.safeClose()方法非常感兴趣。它们是IBM MQ 7.0的一部分吗?(我没有用)还是别的什么?通过搜索找不到太多。在实现我的第一个发送到JMS时,希望避免出现带有大量空检查的丑陋的finally块。@user640118:它们是本地实用工具链的一部分。本质上,他们只是执行空检查并关闭对象,没有火箭科学。