1.背景

我们正在评估Spring JMS并针对各种场景测试JMSTemplate - 队列,主题(持久,非持久) .

我们经历了 message loss for non-durable topic subscribers ,并希望在此处寻求澄清 .

2.问题陈述

a)我们编写了一个独立的java程序,它每隔n秒调用JMSTemplate.receive方法,从非持久主题**同步接收消息 .

b)我们注意到总是 message loss after the 1st invocation of the JMSTemplate.receive method . 这是由于JMSTemplate.receive方法 stopping the connection 到达ConnectionFactoryUtils.releaseConnection(...)时 .

JmsTemplate的:

public <T> T execute(SessionCallback<T> action, boolean startConnection) throws JmsException 
{
        Assert.notNull(action, "Callback object must not be null");
        Connection conToClose = null;
        Session sessionToClose = null;
        try {
              Session sessionToUse = ConnectionFactoryUtils.doGetTransactionalSession(
                          getConnectionFactory(), this.transactionalResourceFactory, startConnection);
              if (sessionToUse == null) {
                    conToClose = createConnection();
                    sessionToClose = createSession(conToClose);
                    if (startConnection) {
                          conToClose.start();
                    }
                    sessionToUse = sessionToClose;
              }
              if (logger.isDebugEnabled()) {
                    logger.debug("Executing callback on JMS Session: " + sessionToUse);
              }
              return action.doInJms(sessionToUse);
        }
        catch (JMSException ex) {
              throw convertJmsAccessException(ex);
        }
        finally {
              JmsUtils.closeSession(sessionToClose);
              ConnectionFactoryUtils.releaseConnection(conToClose, getConnectionFactory(), startConnection); // the connection is stopped here
        }
  }

ConnectionFactoryUtils.releaseConnection(...):

public static void releaseConnection(Connection con, ConnectionFactory cf, boolean started) {
            if (con == null) {
                  return;
            }
            if (started && cf instanceof SmartConnectionFactory && ((SmartConnectionFactory) cf).shouldStop(con)) {
                  try {
                        con.stop(); // connection was stopped here
                  }
                  catch (Throwable ex) {
                        logger.debug("Could not stop JMS Connection before closing it", ex);
                  }
            }
            try {
                  con.close();
            }
            catch (Throwable ex) {
                  logger.debug("Could not close JMS Connection", ex);
            }

3.使用Spring文档验证

Spring JMS文档建议使用池化连接,因此我们确保完成了 .

我们的java程序是从WLS JMS和MQ JMS(LDAP)提供程序获取JMS连接工厂,并在各自的测试用例中使用SingleConnectionFactory和CachingConnectionFactory进行修饰 .

这是我们在测试过程中观察到的:

a)SingleConnectionFactory - 连接已停止(消费者/会话也已关闭) .

b)CachingConnectionFactory - 连接也已停止(尽管Consumer / Session已缓存且未关闭)

4.问题:

a)有人和我们一样遇到过同样的问题吗?

b)您是否认为这是针对非持久性订阅用例的Spring JMS的缺陷?

c)我们正在考虑定制一个不会停止连接的CachingConnectionFactory . 有任何缺点吗?

注意:我们知道使用JMSTemplate的Async MessageListeners(如DMLC / SMLC和Sync Durable Topic Subscribers)不会出现此问题 . 我们只想澄清使用JMSTemplate的Sync Non-Durable主题订阅者 .

非常感谢任何评论和想法 .

谢谢!

胜利者