美文网首页
Cache is not alive (STATUS_SHUTD

Cache is not alive (STATUS_SHUTD

作者: 不知名的蛋挞 | 来源:发表于2019-01-15 20:11 被阅读40次

    错误报警

    [2019-01-07 15:30:25.237] [SIGTERM handler] [INFO] [out-flow-logger] - stopping, Step [5/5] Begin to do shutdownActions,for example spring context
    Exception in thread "SaveThread-pool-1-thread-2" java.lang.IllegalStateException: The callinfo Cache is not alive (STATUS_SHUTDOWN)
        at net.sf.ehcache.Cache$CacheStatus.checkAlive(Cache.java:4075)
        at net.sf.ehcache.Cache.checkStatus(Cache.java:2766)
        at net.sf.ehcache.Cache.get(Cache.java:1727)
        at net.sf.ehcache.Cache.get(Cache.java:1707)
        at com.vip.ads.service.common.queue.DiskQueue.pop(DiskQueue.java:59)
        at com.vip.ads.service.common.queue.SaveThread.run(SaveThread.java:43)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    Exception in thread "SaveThread-pool-1-thread-3" Exception in thread "SaveThread-pool-1-thread-1" java.lang.IllegalStateException: The callinfo Cache is not alive (STATUS_SHUTDOWN)
        at net.sf.ehcache.Cache$CacheStatus.checkAlive(Cache.java:4075)
        at net.sf.ehcache.Cache.checkStatus(Cache.java:2766)
        at net.sf.ehcache.Cache.get(Cache.java:1727)
        at net.sf.ehcache.Cache.get(Cache.java:1707)
        at com.vip.ads.service.common.queue.DiskQueue.pop(DiskQueue.java:59)
        at com.vip.ads.service.common.queue.SaveThread.run(SaveThread.java:43)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    java.lang.IllegalStateException: The callinfo Cache is not alive (STATUS_SHUTDOWN)
        at net.sf.ehcache.Cache$CacheStatus.checkAlive(Cache.java:4075)
        at net.sf.ehcache.Cache.checkStatus(Cache.java:2766)
        at net.sf.ehcache.Cache.get(Cache.java:1727)
        at net.sf.ehcache.Cache.get(Cache.java:1707)
        at com.vip.ads.service.common.queue.DiskQueue.pop(DiskQueue.java:59)
        at com.vip.ads.service.common.queue.SaveThread.run(SaveThread.java:43)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    

    从代码可以知道出错的地方在DiskQueue.pop。原因是Thread还没有执行完,cache就已经关闭了。

    代码review

    @Component
    public class DiskQueue implements InitializingBean {
    
        private static Ehcache cache;
    
        @Resource(name = "ehcacheManager")
        private CacheManager cacheManager;
    
        private static AtomicLong index = new AtomicLong(0);
    
        private static AtomicLong dealIndex = new AtomicLong(0);
    
        private static long getNowIndex(){
            return index.incrementAndGet();
        }
    
        private static long getNowDealIndex() {
            return dealIndex.incrementAndGet();
        }
    
        private static void resetIndex() {
            index.set(0);
        }
    
        private static void resetDealIndex() {
            dealIndex.set(0);
        }
    
        public void push(List<CallInfo> callList) {
            if(null != cache){
                return;
            }
            Element element = new Element(getNowIndex(),callList);
            cache.put(element);
        }
    
        public static List<CallInfo> pop() {
            long nowDealIndex = dealIndex.get();  // 这里出了问题,index并没有增加
            long nowIndex = index.get();
            if(nowDealIndex > nowIndex){
                resetIndex();
                resetDealIndex();
                return null;
            }
    
            if(cache == null){
                return null;
            }
    
            Element element = cache.get(nowDealIndex);   // 出错,cache已经被关闭
            if(element==null){
                return null;
            }
    
            Object obj = element.getObjectValue();
            if(obj == null){
                return null;
            }
            List<CallInfo> callInfos = (List<CallInfo>)obj;
            cache.remove(nowDealIndex);
            return callInfos;
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            EhCacheCache tmpCache = (EhCacheCache) cacheManager.getCache("callinfo");
            cache = tmpCache.getNativeCache();
        }
    }
    

    问题点在于long nowDealIndex = dealIndex.get();这行代码,当队列执行pop操作的时候,拿到的缓存下标一直都是初始化的下标0。第一次pop,是能够成功获取缓存对象的,获取完成就会把下标为0的Element从缓存中删除。那么之后的每次获取拿到的都是null。

    看了下get()方法的源码:

    public final Element get(Serializable key) throws IllegalStateException, CacheException {
            return this.get((Object)key);
        }
    
    public final Element get(Object key) throws IllegalStateException, CacheException {
            this.getObserver.begin();
            this.checkStatus();
            if (this.disabled) {
                this.getObserver.end(GetOutcome.MISS_NOT_FOUND);
                return null;
            } else {
                Element element = this.compoundStore.get(key);
                if (element == null) {
                    this.getObserver.end(GetOutcome.MISS_NOT_FOUND);
                    return null;
                } else if (this.isExpired(element)) {
                    this.tryRemoveImmediately(key, true);
                    this.getObserver.end(GetOutcome.MISS_EXPIRED);
                    return null;
                } else {
                    if (!this.skipUpdateAccessStatistics(element)) {
                        element.updateAccessStatistics();
                    }
    
                    this.getObserver.end(GetOutcome.HIT);
                    return element;
                }
            }
        }
    
    public void end(T result) {
            ((LongAdder)this.counts.get(result)).increment();
            if (!this.derivedStatistics.isEmpty()) {
                long time = Time.time();
                Iterator i$ = this.derivedStatistics.iterator();
    
                while(i$.hasNext()) {
                    ChainedOperationObserver<? super T> observer = (ChainedOperationObserver)i$.next();
                    observer.end(time, result);
                }
            }
    }
    

    从源码看到,如果获取到的Element对象为空,就不仅仅是返回空对象这个简单的操作,还有this.getObserver.end(GetOutcome.MISS_NOT_FOUND)。初步推断Ehcache中有自己的关闭机制,达到n次get()返回为空之后就会自动关闭cache。

    有明确知道这个原因的小伙伴希望私信或评论一下我哈~共同学习进步。

    相关文章

      网友评论

          本文标题:Cache is not alive (STATUS_SHUTD

          本文链接:https://www.haomeiwen.com/subject/dewurqtx.html