sessionStatMap is full
背景
线上的程序,突然报了sessionStatMap is full的error,程序的连接池用的是druid,版本号1.1.11,老大问这是什么错,赶紧修复下。。。。
排查过程
首先去github上的druid中搜索这个错误,发现有如下几个issues:
点进去看了下,也没说到底要不要紧,然后去google上搜了下,也基本没说怎么解决,或者不解决到底影不影响系统运行
没办法,只能去看源码
public WebSessionStat getSessionStat(String sessionId, boolean create) {
sessionStatLock.readLock().lock();
try {
WebSessionStat uriStat = sessionStatMap.get(sessionId);
if (uriStat != null) {
return uriStat;
}
} finally {
sessionStatLock.readLock().unlock();
}
if (!create) {
return null;
}
sessionStatLock.writeLock().lock();
try {
WebSessionStat uriStat = sessionStatMap.get(sessionId);
if (uriStat == null) {
if (sessionStatMap.size() >= this.getMaxStatSessionCount()) {
long fullCount = uriSessionMapFullCount.getAndIncrement();
if (fullCount == 0) {
LOG.error("sessionStatMap is full");
}
}
WebSessionStat newStat = new WebSessionStat(sessionId);
sessionStatMap.put(sessionId, newStat);
return newStat;
}
return uriStat;
} finally {
sessionStatLock.writeLock().unlock();
}
}
可以看到是sessionStatMap的size超过了最大值(1000),然后抛了这个错误,按照常理说,如果大于1000了,应该就不再生成新的WebSessionStat,放到map中了,不然肯定造成map无限大啊
但是看了druid的监控界面,发现监控的session稳定在了1000,没有无限增长,难道map会删除?
看到sessionStatMap的类型是LRUCache,该类重写了removeEldestEntry方法,继续跟踪,在map的afterNodeInsertion中调用了removeEldestEntry(删除元素),然后在putVal中的最后调用了afterNodeInsertion,这时疑惑就解开了,继续put的时候会在添加完后删除第一个元素,所以map一直维持在1000的大小
总结
这个sessionStatMap is full的error就是相当于个提示信息,告诉你监控的session个数达到了1000了,后续不会增长了(加入新的删除老的),其实打个warn就行了,打成error,我们时不时就接到这个报警