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,我們時不時就接到這個報警