在集成activemq 到web开发环境中遇到问题: 项目运行一段时间后 在调用produce 发送消息会报错 session is closed。
在查看PooledConnectionFactory, 结合网上查询的资料。
popl.setMaxConnections(2); 最大connection数
popl.setMaximumActiveSessionPerConnection(30); 设置最大session数量
1, PooledConnectionFactory.createConnection() 会将Connection缓存起来。
源码创建的代码如下
PooledConnectionFactory.java
public synchronized Connection createConnection(String userName, String password) throws JMSException {
if (this.stopped.get()) {
LOG.debug("PooledConnectionFactory is stopped, skip create new connection.");
return null;
} else {
ConnectionPool connection = null;
ConnectionKey key = new ConnectionKey(userName, password);
if (this.getConnectionsPool().getNumIdle(key) < this.getMaxConnections()) {
try {
this.connectionsPool.addObject(key);
connection = (ConnectionPool)this.mostRecentlyCreated.getAndSet((Object)null);
connection.incrementReferenceCount();
} catch (Exception var8) {
throw this.createJmsException("Error while attempting to add new Connection to the pool", var8);
}
} else {
try {
while(connection == null) {
connection = (ConnectionPool)this.connectionsPool.borrowObject(key);
synchronized(connection) {
if (connection.getConnection() != null) {
connection.incrementReferenceCount();
break;
}
this.connectionsPool.returnObject(key, connection);
connection = null;
}
}
} catch (Exception var10) {
throw this.createJmsException("Error while attempting to retrieve a connection from the pool", var10);
}
try {
this.connectionsPool.returnObject(key, connection);
} catch (Exception var7) {
throw this.createJmsException("Error when returning connection to the pool", var7);
}
}
return this.newPooledConnection(connection);
}
}
2, PooledConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); 不会缓存session。 只会往PooledConnection的loanedSessions 中添加。 调用一次就添加一次。 源码如下
PooledConnection.java
private final List<PooledSession> loanedSessions = new CopyOnWriteArrayList();
public Session createSession(boolean transacted, int ackMode) throws JMSException {
PooledSession result = (PooledSession)this.pool.createSession(transacted, ackMode);
this.loanedSessions.add(result);
result.addSessionEventListener(this);
return result;
}
3, 现在代码调整为 每次消费者都去 创建session, 发送完后就销毁。 (待测试是否还会出现 session is closed)
try {
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(....);
}finally {
if(producer != null){
producer.close();
}
if(session != null){
session.close(); // 销毁
}
}
4, JmsTemplate(spring整合activemq) 每次发送消息后都关闭了 producer 和 session
JmsTemplate.java
JmsUtils.closeSession(sessionToClose);
ConnectionFactoryUtils.releaseConnection(conToClose, this.getConnectionFactory(), startConnection);
https://www.jianshu.com/p/981b30ad9def session is closed 发生的原因
https://www.iteye.com/blog/cesymm-2003380 activemq对connection的管理
http://www.voidcn.com/article/p-rbmuatof-btp.html 对PooledConnectionFactory的分析