我们在JMS应用程序的发送方使用Spring的CachingConnectionFactory,它向Tibco EMS发送消息。
我们在重启EMS代理或存在容错交换机时遇到问题。
在CachingConnectionFactory中处理异常处理的调用会挂起并保持锁定,以防止将来客户端调用EMS。
这是堆栈跟踪
TIBCO EMS TCPLink Reader (Server-880629)" - Thread t@457
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
- waiting on <20035387> (a com.tibco.tibjms.TibjmsxResponse)
at java.lang.Object.wait(Object.java:502)
at com.tibco.tibjms.TibjmsxLink.sendRequest(TibjmsxLink.java:359)
at com.tibco.tibjms.TibjmsxLink.sendRequestMsg(TibjmsxLink.java:293)
at com.tibco.tibjms.TibjmsxSessionImp._close(TibjmsxSessionImp.java:2836)
at com.tibco.tibjms.TibjmsxSessionImp.close(TibjmsxSessionImp.java:4800)
at org.springframework.jms.connection.CachingConnectionFactory$CachedSessionInvocationHandler.physicalClose(CachingConnectionFactory.java:487)
at org.springframework.jms.connection.CachingConnectionFactory$CachedSessionInvocationHandler.invoke(CachingConnectionFactory.java:317)
at com.sun.proxy.$Proxy263.close(Unknown Source)
at org.springframework.jms.connection.CachingConnectionFactory.resetConnection(CachingConnectionFactory.java:184)
- locked <37550f2a> (a java.util.LinkedList)
- locked <7e847e44> (a java.util.HashMap)
at org.springframework.jms.connection.SingleConnectionFactory.onException(SingleConnectionFactory.java:360)
at org.springframework.jms.connection.SingleConnectionFactory$AggregatedExceptionListener.onException(SingleConnectionFactory.java:716)
at com.tibco.tibjms.TibjmsConnection._invokeOnExceptionCallback(TibjmsConnection.java:2029)
at com.tibco.tibjms.TibjmsConnection._reconnect(TibjmsConnection.java:1902)
at com.tibco.tibjms.TibjmsConnection$ServerLinkEventHandler.onEventReconnect(TibjmsConnection.java:364)
at com.tibco.tibjms.TibjmsxLinkTcp._doReconnect(TibjmsxLinkTcp.java:602)
at com.tibco.tibjms.TibjmsxLinkTcp$LinkReader.work(TibjmsxLinkTcp.java:319)
- locked <405e282> (a java.lang.Object)
at com.tibco.tibjms.TibjmsxLinkTcp$LinkReader.run(TibjmsxLinkTcp.java:259)
基本上有两个锁。第一个(在上面的堆栈跟踪中表示为锁定&lt; 405e282&gt;)与其他线程共享,并阻止任何线程发送新请求
synchronized (TibjmsxLinkTcp.this._sendLock)
/* */ {
/* 315 */ if ((TibjmsxLinkTcp.this._state == 1) &&
/* */
/* 317 */ (TibjmsxLinkTcp.this._doReconnect(false))) {
/* 318 */ break label0:
/* */ }
/* */ }
这似乎足够合理。问题出在另一个锁上,表示为 &LT; 20035387&GT;在堆栈跟踪中
try
/* */ {
/* 335 */ send(paramObject, i, localTibjmsxResponse);
/* */ }
…
synchronized (localTibjmsxResponse)
/* */ {
/* 351 */ while (localTibjmsxResponse.status == 0)
/* */
/* */
/* */ {
/* */ try
/* */ {
/* 357 */ if (paramLong < -1L)
/* 358 */ localTibjmsxResponse.wait(-paramLong);
/* */ else localTibjmsxResponse.wait();
/* */
/* */ }
/* */ catch (InterruptedException localInterruptedException)
/* */ {
/* 364 */ ??? = Tibjmsx.buildException("InterruptedException has occurred while waiting for server response", null, localInterruptedException);
/* */ }
/* */
/* */ }
localTibjmsxResponse上的标志永远不会更改,因此线程会挂起。
我认为将Spring的CachingConnectionFactory与EMS结合使用是相当普遍的,不知其他人是否遇到同样的问题并知道解决方案是什么?
以下是我们创建配置的方法
public ConnectionFactory jmsConnectionFactory() {
if (logger.isInfoEnabled()) {
logger.info(
new StringBuilder("Initialising JMSSender using providerUrl=").append(this.providerUrl)
.append(", username=").append(this.username)
.append(", pass=").append(this.password)
.append(", attemptCount=").append(this.attemptCount)
.append(", attemptTimeout=").append(this.attemptTimeout)
.append(", attemptDelay=").append(this.attemptDelay).toString());
}
Tibjms.setExceptionOnFTSwitch(true);
TibjmsTopicConnectionFactory topicConnectionFactory = new TibjmsTopicConnectionFactory(providerUrl);
topicConnectionFactory.setUserName(username);
topicConnectionFactory.setUserPassword(password);
topicConnectionFactory.setConnAttemptCount(attemptCount);
topicConnectionFactory.setConnAttemptTimeout(attemptTimeout);
topicConnectionFactory.setConnAttemptDelay(attemptDelay);
topicConnectionFactory.setReconnAttemptCount(attemptCount);
topicConnectionFactory.setReconnAttemptTimeout(attemptTimeout);
topicConnectionFactory.setReconnAttemptDelay(attemptDelay);
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(topicConnectionFactory);
cachingConnectionFactory.setReconnectOnException(true);
cachingConnectionFactory.setExceptionListener(new JMSExceptionListener());
cachingConnectionFactory.setSessionCacheSize(10);
TransactionAwareConnectionFactoryProxy transactionAwareConnectionFactoryProxy = new TransactionAwareConnectionFactoryProxy();
transactionAwareConnectionFactoryProxy.setTargetConnectionFactory(cachingConnectionFactory);
transactionAwareConnectionFactoryProxy.setSynchedLocalTransactionAllowed(true);
return transactionAwareConnectionFactoryProxy;
}
谢谢, 尼克