2017-07-04 24 views
2

我使用Http.Current.Cache來存儲從我的數據庫檢索的各種值,因爲我的應用程序是數據密集型的。當我在VS2017安裝的新筆記本電腦上運行我的網站時(在VS2015的另一臺筆記本電腦上我從來沒有看到這個問題),我看到一個非常奇怪的問題,即緩存值似乎被隨機清除 - 幾乎是以一種違背邏輯的方式。如何在單線程中使緩存值失效?

例如,我有一個如果子句的條件是所討論的緩存項不爲空。我的代碼肯定是沿着通過這條如果語句的路徑,但稍後調試器顯示緩存項實際上爲空 - 導致我的應用程序失敗。

public static SportSeason GetCurrentSportSeason(string sportCode) 
{ 
    SportSeason sportSeason = null; 
    string key = "Sheets_SportSeason_" + sportCode; 

    int i = 0; 
    if (BaseSheet.Settings.EnableCaching && BizObject.Cache[key] != null) 
    { 
    i = 1; 
    sportSeason = (SportSeason)BizObject.Cache[key]; 
    } 
    else 
    { 
    i = 2; 
    sportSeason = GetSportSeasonFromSportSeasonDetails(SiteProvider.Sheets.GetCurrentSportSeason(sportCode)); 
    BaseSheet.CacheData(key, sportSeason); 
    } 
    if(sportSeason == null) 
    { 
    int j = i; 
    } 
    return sportSeason; 
} 

我可以在最終設置斷點,如果並且變量i設置爲1,但sportSeason目的是NULL(因爲是高速緩存條目)。當代碼可能已經進入第一個子句時,如果緩存項不爲空,這怎麼可能呢?

這是一個屏幕截圖,顯示了一些在最終if中帶有斷點的監視變量。 enter image description here

這很難追查,因爲它在我的業務對象中隨機發生。有時我必須刷新頁面3到4次,才能看到這些問題。

如何快速使緩存失效,以及通過什麼?屏幕截圖顯示緩存項目不多,所以我認爲我的內存不足。並沒有其他進程正在運行,可能會破壞緩存。

編輯:通過更多的調試,我已經確定,只有在第91行檢查的緩存鍵被清除(設置爲空),當它再次檢查斷點時。所有其他緩存記錄仍然存在。

EDIT2:我已經分離出的問題到這一點,但它似乎仍然違反邏輯:

HttpContext.Current.Cache.Insert("ABC", "123", null, DateTime.Now.AddSeconds(600), TimeSpan.Zero); 
    int i = 0; 

清除我的所有緩存。當我跨越Cache.Insert語句時,我的緩存計數將變爲1.但是,根據該密鑰的緩存項仍爲空(請參閱監視窗口)。

enter image description here

另外,如果我執行一個以上的語句(包括int i = 0),緩存計數回零。

enter image description here

EDIT3:這是殺害我插入()的則absoluteExpiration參數。不知怎的,一個時鐘關閉。

如果我將AbsoluteExpiration設置爲未來5小時(300分鐘),則不起作用。如果將其設置爲未來5小時1分鐘(301分鐘),則一切正常。

HttpContext.Current.Cache.Insert("ABC", "123", null, DateTime.Now.AddMinutes(301), TimeSpan.Zero); 

我的筆記本電腦上的時鐘是100%準確的,你可以看到Intellisense顯示正確的時間。緩存可以基於5小時關閉的其他時鐘嗎?

enter image description here

Edit4:看起來像someone else is off by 5 hours

+0

在您定義的過程中,你有沒有試圖挽救了'偶然web.config'/ – Webruster

+0

@Webruster沒有,什麼也沒有被除了頁面加載完成 – bperniciaro

+0

可您發佈的頁面加載代碼/ – Webruster

回答

6

修復方法是始終使用DateTime。 Utc指定AbsoluteExporation參數時,現在不使用DateTime.Now。

這樣做:

HttpContext.Current.Cache.Insert("ABC", "123", null, DateTime.UtcNow.AddMinutes(1), System.Web.Caching.Cache.NoSlidingExpiration); 

不是這個:

HttpContext.Current.Cache.Insert("ABC", "123", null, DateTime.Now.AddMinutes(1), System.Web.Caching.Cache.NoSlidingExpiration); 

當我做到這一點,正確地認識到,緩存是有效的,我可以檢索該值。至於爲什麼這是我的Windows 10 Pro筆記本電腦而不是我的Windows 10家庭版上所需的,我不知道。

+1

如果您使用不同格式的日期時間,它可能會影響某些內部Windows功能。有時當用戶使用HH:MM格式時,我有同樣的問題... –

0

查看您的IIS應用程序池回收選項以排除回收事件。因爲application pool recycle, will clear your cache

Per the App pool recycling settings docs

可以指定IIS每天回收以設定的間隔 (每180分鐘如)一個應用程序池,在特定的時間,或 應用程序池之後接收一定數量的請求。當 工作進程虛擬內存和物理內存使用率達到 特定閾值時,您也可以配置該元素以重新啓動應用程序池。

即使更改您的配置也可以回收應用程序池。

確保沒有其他應用程序共享您的應用程序池,然後打開回收日誌記錄並重現此問題。查看緩存消失是否與日誌中的應用程序池回收相關。如果是這樣,請從此處確定回收過程發生的原因,然後更改配置,以便應用程序池在正常運行時間內不會回收。

+1

我認爲這個理論的問題在於代碼沿着(1)路徑,在這一點上緩存值必須被加載。如果緩存在該點之後被清除,那麼所有的緩存都應該是空的。但是,如果您查看截圖中的監視變量,則可以看到我的很多項目仍處於緩存中。 – bperniciaro

+1

我驗證了沒有發生應用程序池回收操作。 – bperniciaro

2

您可以添加一個回調函數,它可以告訴你,爲什麼已刪除項目:

https://msdn.microsoft.com/en-us/library/7kxdx246.aspx

您添加項目時指定回調,並且當物品被刪除,將被解僱。在那裏放置一個斷點或日誌輸出來打印出CacheItemRemovedReason參數。

如果這對您沒有幫助,您可以嘗試在ASP.NET HttpContext Cache removes right after insertion的頂部答案中列出的調試步驟。如果應用程序正在終止,這可能會被捕獲。

+0

這是系統時間的問題。我必須將我的AbsoluteExpiration時間設置爲未來至少5個小時,否則將立即失效。 – bperniciaro