我们正在评估Spring JMS并针对各种场景测试JMSTemplate - 队列,主题(持久,非持久)。
我们遇到了非持久主题订阅者的消息丢失,并希望在此处寻求澄清。
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);
}
Spring JMS文档建议使用池化连接,因此我们确保完成了。
我们的java程序是从WLS JMS和MQ JMS(LDAP)提供程序获取JMS连接工厂,并在各自的测试用例中使用SingleConnectionFactory和CachingConnectionFactory进行修饰。
这是我们在测试期间观察到的:
a)SingleConnectionFactory - 连接已停止(消费者/会话也已关闭)。
b)CachingConnectionFactory - 连接也已停止(尽管消费者/会话被缓存而未关闭)
a)有人和我们一样遇到过同样的问题吗?
b)您是否认为这是针对非持久性订阅用例的Spring JMS的缺陷?
c)我们正在考虑定制一个不会停止连接的CachingConnectionFactory。有任何缺点吗?
注意:我们知道使用JMSTemplate的Async MessageListeners(如DMLC / SMLC和Sync Durable Topic Subscribers)不会出现此问题。我们只想澄清使用JMSTemplate的Sync Non-Durable主题订阅者。
非常感谢任何评论和想法。
谢谢!
维克多