Spring DMS模板同步接收非持久用户消息丢失

时间:2017-03-29 02:26:27

标签: spring jms subscriber

1。背景

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

我们遇到了非持久主题订阅者的消息丢失,并希望在此处寻求澄清。

2。问题陈述

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

b)我们注意到在第一次调用JMSTemplate.receive方法后总是有消息丢失。这是由于JMSTemplate.receive方法在到达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 - 连接也已停止(尽管消费者/会话被缓存而未关闭)

4。问题:

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

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

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

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

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

谢谢!

维克多

0 个答案:

没有答案