在圖靈社群實現快取他人頭像,而對本人不快取
在圖靈社群的開發中有這樣一個情況:
會員的頭像有三種大小,由於檔案都很小,就選擇存在資料庫中了。每個頁面有大量的 GetAvatar(id, size) 請求,對應於 http://www.ituring.com.cn/users/getavatar/82554?size=small,根據會員Id和要求的尺寸這兩個引數,返回的相應的頭像檔案。
頭像很少變化,並且某個人的頭像換了,其他的人晚一點看到新頭像,不影響使用,因此可以使用快取。但是如果某個會員自己重新上傳了頭像,那麼必然要求能立刻看到新頭像,而不能等到若干小時之後快取更新以後才看到,這是一個必須的約束條件。
此外,這個快取要同時考慮 Server 端快取和 Browser 端的快取。
這裡要說明的主要是基於在 ASP.NET 框架本身的實現基於使用者的差異快取的方法,並不是討論這樣處理一個網站的頭像檔案儲存應該怎麼做更好的問題。這裡僅用頭像儲存作為一個具體的案例。
Step 1
在 GetAvatar() 方法上使用 OutputCacheAttribute 特性,並指定快取的時間為 1 天:
[OutputCache(Duration= 3600*24)]
public ActionResult GetAvatar(int id, AvatarSize size)
{
// 省略
}
Step 2
Step 1 中實現了基本的快取功能,同時在 Server 和 Browser 端都有效。但是問題在於,如果一個會員在其個人空間更新了頭像,那麼他也要等到下次更新的時候才能看到新頭像。因此使用OutputCacheAtribute的VaryByCustom引數:
[OutputCache(Duration= 3600*24, VaryByCustom="getAvatar")]
public ActionResult GetAvatar(int id, AvatarSize size)
{
// 省略
}
並在 Global.asax.cs 中重寫 GetVaryByCustomString:
public override string GetVaryByCustomString(HttpContext context, string arg)
{
if (arg == "getAvatar")
{
var id = context.Request.Cookies["iTuringUserId"];
return id != null && id.Value == Request.Path.Split('/')[3]
? DateTime.Now.Ticks.ToString()
: context.Request.Path.Split('/')[3] + Request.Params["size"];
}
return base.GetVaryByCustomString(context, arg);
}
這個函式在呼叫 GetAvatar() 方法之前呼叫,OutputCacheAttribute 會根據你返回的值決定快取的版本。因此,在這個函式中,將請求的 cookies 中的會員的 Id 和所請求的頭像的 Id 進行比較,如果相同說明是本人的請求,則返回一個隨機數(這裡用時間,效果一樣),這樣每次返回這個值都是新值。因此就會取得新的頭像。如果不同,就返回Id和尺寸的組合,這樣就可以使用快取的版本了。
Step 3
Step 2 中已經可以實現根據會員來決定是否使用快取的頭像,但是剩下的問題是,對於本人的請求,第一次返回的時候,設定了 Browser 上的快取,這個快取設定是統一的,都是1天,這樣會導致某個頭像的本人瀏覽頁面時,由於瀏覽器上設定了快取,而根本不會像伺服器發出請求,從而無法得到新的頭像。
因此需要在返回頭像檔案的時候,根據使用者來決定是否設定HTTP頭的快取:
[OutputCache(Duration= 3600*24, VaryByCustom="getAvatar")]
public ActionResult GetAvatar(int id, AvatarSize size)
{
if (Request.Cookies["iTuringUserId"] != null
&& Request.Cookies["iTuringUserId"].Value == id.ToString())
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
}
// 省略
}
好了,大功告成!
這樣的結果是,顯示非本人頭像的請求的CPU時間降到了0.1ms,而如果直接從資料庫取出並返回,則需要 50~100ms 。而圖靈社群上,很多頁面都要顯示幾十個頭像,因此這個優化還是很有價值的。
此外,這裡的方法具有通用性,能夠實現針對使用者輸出不同的快取版本。
相關文章
- SDWebImage實現圖片展示、快取、清除快取Web快取
- 擷取圖片生成頭像外掛
- 因圖靈測試而認識圖靈社群(知道圖靈測試後對未來人工智慧侃侃而談)圖靈人工智慧
- 【倡議】所有圖靈社群成員使用實名ID並上傳真實頭像圖靈
- 因圖靈測試而認識圖靈社群(知道圖靈測試後對未來人工智慧侃侃而談)2圖靈人工智慧
- http頭部如何對快取的控制HTTP快取
- nginx強制不快取Nginx快取
- 兩級快取實現分析之快取設定快取
- 對Jquery上傳頭像擷取程式碼的更新jQuery
- Maven高手在圖靈社群?!Maven圖靈
- 使用RxJava實現快取RxJava快取
- LRU快取實現(Java)快取Java
- WebRTC從攝像頭獲取圖片傳入canvasWebCanvas
- vue怎麼設定html不快取 但是js、css等檔案做快取VueHTML快取JSCSS
- SpringBoot快取管理(二) 整合Redis快取實現Spring Boot快取Redis
- QQ群頭像 微信群頭像 多圖合併框架實現框架
- Vue專案全域性配置頁面快取,實現按需讀取快取Vue快取
- 快取圖片快取
- 圖片快取快取
- 對於前端快取的理解(快取機制和快取型別)前端快取型別
- 實現AVPlayer離線快取快取
- 使用ConcurrentHashMap實現快取HashMap快取
- 資料快取的實現快取
- 在 WPF 客戶端實現 AOP 和介面快取客戶端快取
- 微信小程式 實現網路圖片本地快取微信小程式快取
- Laravel 實現二級快取 提高快取的命中率和細粒化快取 keyLaravel快取
- Web快取基礎:術語、HTTP報頭和快取策略Web快取HTTP
- 酷酷大頭貼,酷酷大頭像。一寸兩寸三分鐘快取。快取
- WEB 應用快取解析以及使用 Redis 實現分散式快取Web快取Redis分散式
- 對圖靈社群改版的小看法圖靈
- Python基於opencv呼叫攝像頭獲取個人圖片PythonOpenCV
- CircleImageView 圓形圖片頭像實現View
- laravel利用Redis來實現網站快取讀取LaravelRedis網站快取
- 為什麼要用快取伺服器以及在 Java 中實現一個 redis 快取服務快取伺服器JavaRedis
- 圖靈社群圖靈
- Android使用LruCache、DiskLruCache實現圖片快取+圖片瀑布流Android快取
- 圖解 HTTP 快取圖解HTTP快取
- 圖解HTTP快取圖解HTTP快取