CentOs7.5安裝FFmpeg

  2019-04-21 11:16:32 [http-nio-4081-exec-2] WARN  com.google.common.cache.LocalCache - Exception thrown during refresh
  
  com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key BKCIYear0.
  
  at com.google.common.cache.LocalCache$Segment.getAndRecordStats(LocalCache.java:2350)
  
  at com.google.common.cache.LocalCache$Segment$1.run(LocalCache.java:2331)
  
  at com.google.common.util.concurrent.MoreExecutors$DirectExecutor.execute(MoreExecutors.java:457)
  
  at com.google.common.util.concurrent.ExecutionList.executeListener(ExecutionList.java:156)
  
  at com.google.common.util.concurrent.ExecutionList.add(ExecutionList.java:101)
  
  at com.google.common.util.concurrent.AbstractFuture.addListener(AbstractFuture.java:170)
  
  at com.google.common.cache.LocalCache$Segment.loadAsync(LocalCache.java:2326)
  
  at com.google.common.cache.LocalCache$Segment.refresh(LocalCache.java:2389)
  
  at com.google.common.cache.LocalCache$Segment.scheduleRefresh(LocalCache.java:2367)
  
  at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2187)
  
  at com.google.common.cache.LocalCache.get(LocalCache.java:3937)
  
  at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941)
  
  at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824)
  
  at com.kcidea.sushibase.Service.Cache.GoogleLocalCache.getCacheByName(GoogleLocalCache.java:42)
  
  google的這個開發工具裏面的緩存是個輕量化的緩存,相似一個HashMap的實現,google在裏面加了不少同步異步的操做。使用起來簡單,不用額外搭建redis服務,故項目中使用了這個緩存。
  
  有一天生產環境直接假死了,趕忙上服務器排查,發現日誌裏面有大量的報WARN錯誤,只要觸發cache的get就會報警告,因爲cache的觸發頻率超高,致使了日誌磁盤爆滿,一天好幾個G的日誌裏面全是WARN的錯誤。可是在開發環境下根本不觸發這個錯誤,怎麼調試都沒有進這段代碼裏面。先暫時停用了緩存,而後開始排查。
  
  2、問題排查
  
  1. 根據報錯的堆棧,一點一點往上找,直到找到這一行的時候發現了一些端倪,他想找一個newValue
  
  at com.google.common.cache.LocalCache$Segment.refresh(LocalCache.java:2389)
  
  2. 繼續順着這條線往裏面找,直到找到這段代碼,爲何要找newValue呢,map須要刷新了,過時了,或者主動觸發刷新值了。
  
  if (map.refreshes()
  
  && (now - entry.getWriteTime() > map.refreshNanos)
  
  && !entry.getValueReference().isLoading()) {
  
  V newValue = refresh(key, hash, loader, true);
  
  if (newValue != null) {
  
  return newValue;
  
  }
  
  }
  
  3. 而後就能夠解釋問題爲何只在生產環境出現,而開發環境不出現了,由於是觸發了過時時間,咱們設置的過時時間是30分鐘,因此開發環境不多調試超過30分鐘的,每次都是從新運行,因此根本觸發不到這個超時的地方。
  
  4. 而後接着調試,發現會走到咱們一開始初始化cache的代碼那邊
  
  /**
  
  * 緩存隊列變量
  
  */
  
  static LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
  
  // 給定時間內沒有被讀/寫訪問,則回收。
  
  .refreshAfterWrite(CACHE_OUT_TIME, TimeUnit.MINUTES)
  
  // 緩存過時時間和redis緩存時長同樣
  
  .expireAfterAccess(CACHE_OUT_TIME, TimeUnit.MINUTES)
  
  // 設置緩存個數
  
  .maximumSize(50000).
  
  build(new CacheLoader<String, Object>() {
  
  @Override
  
  public Object load(String key) throws Exception {
  
  //找不到就返回null (1)
  
  return null;
  
  }
  
  http://www.wanxinyulept.com/chaoyue/
  
  注意上面的代碼,(1)的位置,找不到就返回null,在網上找的代碼裏面這裏一般寫的是return null或者return doThingsTheHardWay(key)之類的,可是沒有詳細的doThingsTheHardWay描述,因此我這裏寫了個null。
  
  因此根本的問題就是這裏返回null致使的錯誤了。
  
  3、解決方案
  
  找到了問題緣由,解決方案就相對來講容易的不少了
  
  1. 修改(1)處的代碼,將return null修改爲return new NullObject()
  
  static LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
  
  // 給定時間內沒有被讀/寫訪問,則回收。
  
  .refreshAfterWrite(CACHE_OUT_TIME, TimeUnit.MINUTES)
  
  // 緩存過時時間和redis緩存時長同樣
  
  .expireAfterAccess(CACHE_OUT_TIME, TimeUnit.MINUTES)
  
  // 設置緩存個數
  
  .maximumSize(50000).
  
  build(new CacheLoader<String,http://www.zzhehong.com/chaoyue/ Object>() {
  
  @Override
  
  public Object load(String key) throws Exception {
  
  //嘗試將這裏改爲new NullObject,外面進行判斷
  
  return new NullObject(www.dfyldl.com);
  
  }
  
  });
  
  2. 定義一個空白的類就叫NullObject
  
  /**
  
  * ClassName   NullObject
  
  * Author      shenjing
  
  * Date        2019/7/10
  
  * Version     1.0
  
  **/
  
  public class NullObject {
  
  }
  
  3. 在通用的getCacheByName的方法中進行判斷,取到的對象是否是NullObject類型的,若是是,則返回null給外層,進行從新加載。
  
  private static <www.yuechaoyule.com> T getCacheByName(String name) {
  
  T ret = null;
  
  try {
  
  if (cache.asMap().containsKey(name)) {
  
  ret = (T) cache.get(name);
  
  if (ret.getClass(www.chaoyueylgw.com).equals(NullObject.class)) {
  
  //緩存已過時,返回null
  
  return null;
  
  }
  
  log.debug("緩存讀取[{www.yuechaoyule.com}]成功", name);
  
  }
  
  } catch (Exception ex) {
  
  log.debug("緩存[{}]讀取失敗:{www.yfzc7.com}", name, ex.getMessage());
  
  }
  
  return ret;
  
  }java

相關文章
相關標籤/搜索