2016-06-08 46 views
0

我目前正在調用外部服務並緩存HttpContext.Current.Items集合中的一些數據以獲得性能。數據可以定期更改,並且對用戶敏感,這就是爲什麼我們目前只在當前HttpRequest期間存儲它。跨線程訪問存儲在HttpContext.Current.Items中的數據

例子:

if (HttpContext.Current.Items[cacheKey] != null) 
{ 
    LogHelper.Debug<ExampleService>("[- CACHED RESULT -] GetUser({0})",() => email); 
    return (ExampleUser)HttpContext.Current.Items[cacheKey]; 
} 

using (var client = new UserServiceClient()) 
{ 
    using (new OperationContextScope(client.InnerChannel)) 
    { 
     LogHelper.Debug<ExampleService>("GetUser({0})",() => email); 
     exampleUser = svc.GetUser(email); 
     HttpContext.Current.Items.Add(cacheKey, exampleUser); 
    } 
} 

在我的本地環境中,此行爲與預期相同,大多也不會在分期在同一個線程用於請求期間然而,在生產,這是情況並非如此,有仍然在同一個請求中多次調用外部服務。這可以從日誌中看出,它顯示在線程ID與原始請求不匹配的情況下,HttpContext.Current.Items[cacheKey]中的值不會返回。

這個我猜意思是我目前對HttpContext.Current.Items的理解是錯誤的,並且這不適合我的需要。

因此,我的問題是可以在同一個請求中的多個線程中工作嗎?如果是這樣的話,否則有什麼合適的選擇?

+0

HttpContext.Current是每個線程,因爲你已經發現了你自己。如果要在其他某個線程中使用當前請求的HttpContext.Current - 首先在當前線程中獲取對它的引用,然後將其傳遞給另一個線程。 – Evk

+0

HttpContext.Current.Session是專用於單個用戶的區域;存儲在會話中的任何對象將僅可用於創建它的用戶/會話。 – Eldho

+0

我知道使用會話存儲不是一個好主意,因爲內存使用情況(這是可能存儲的許多項目之一),但是,如果站點後來進入負載平衡環境,它不可擴展。 – ProNotion

回答

0

一種選擇是使用會話來存儲您的數據。不幸的是,它不適用於特定於API的請求(例如移動設備調用服務器API)。此外,服務器會話狀態要求所有數據可串行化(數據庫會話狀態不)。

如果會話不滿足您的要求,那麼您應該轉到下一個選項:使用表示來自同一用戶(也稱爲訪問令牌)的請求的內容保護緩存。