使用輸出快取改善效能 (C#)
由Microsoft提供
在本教學課程中,您將瞭解如何利用輸出快取,大幅改善 ASP.NET MVC Web 應用程式的效能。 您將瞭解如何快取從控制器動作傳回的結果,如此一來,每次新的使用者叫用動作時,都不需要建立相同的內容。
本教學課程的目標是要說明如何利用輸出快取,大幅改善 ASP.NET MVC 應用程式的效能。 輸出快取可讓您快取控制器動作所傳回的內容。 如此一來,每次叫用相同的控制器動作時,都不需要產生相同的內容。
例如,假設您的 ASP.NET MVC 應用程式會在名為 Index 的檢視中顯示資料庫記錄清單。 一般而言,每次使用者叫用傳回索引檢視的控制器動作時,都必須藉由執行資料庫查詢,從資料庫擷取一組資料庫記錄。
另一方面,如果您利用輸出快取,則您可以避免每次使用者叫用相同的控制器動作時執行資料庫查詢。 您可以從快取擷取檢視,而不是從控制器動作重新產生。 快取可讓您避免在伺服器上執行備援工作。
啟用輸出快取
您可以將 [OutputCache] 屬性新增至個別控制器動作或整個控制器類別,以啟用輸出快取。 例如,清單 1 中的控制器會公開名為 Index () 的動作。 Index () 動作的輸出會快取 10 秒。
清單 1 – Controllers\HomeController.cs
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
[OutputCache(Duration=10, VaryByParam="none")]
public ActionResult Index()
{
return View();
}
}
}
在 ASP.NET MVC 的 Beta 版本中,輸出快取不適用於類似 http://www.MySite.com/
的 URL。 相反地,您必須輸入類似 的 http://www.MySite.com/Home/Index
URL。
在清單 1 中,Index () 動作的輸出會快取 10 秒。 如果您想要的話,您可以指定較長的快取持續時間。 例如,如果您想要快取控制器動作的輸出一天,則可以指定快取持續時間 86400 秒 (60 秒 * 60 分鐘 * 24 小時) 。
不保證內容會快取您指定的時間量。 當記憶體資源變低時,快取會自動開始收回內容。
清單 1 中的主控制器會傳回清單 2 中的索引檢視。 此檢視沒有任何特殊之處。 [索引] 檢視只會顯示目前的時間 (請參閱圖 1) 。
清單 2 – Views\Home\Index.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
</head>
<body>
<div>
The current time is: <%= DateTime.Now.ToString("T") %>
</div>
</body>
</html>
圖 1 – 快取索引檢視
如果您在瀏覽器的網址列中輸入 URL /Home/Index 多次叫用 Index () 動作,並在瀏覽器中重複按下 [重新整理/重載] 按鈕,則 [索引] 檢視所顯示的時間將不會變更 10 秒。 因為已快取檢視,所以會顯示相同的時間。
請務必瞭解相同的檢視會快取給造訪您應用程式的每個人。 叫用 Index () 動作的任何人都可以取得相同的索引檢視快取版本。 這表示網頁伺服器必須執行才能提供索引檢視的工作量大幅減少。
清單 2 中的檢視會非常簡單。 檢視只會顯示目前的時間。 不過,您可以輕鬆地快取顯示一組資料庫記錄的檢視。 在此情況下,每次叫用傳回檢視的控制器動作時,都不需要從資料庫擷取一組資料庫記錄。 快取可以減少網頁伺服器和資料庫伺服器必須執行的工作量。
請勿在 MVC 檢視中使用頁面 < %@ OutputCache % > 指示詞。 此指示詞來自Web Form世界,不應在 ASP.NET MVC 應用程式中使用。
快取內容的位置
根據預設,當您使用 [OutputCache] 屬性時,內容會快取三個位置:網頁伺服器、任何 Proxy 伺服器和網頁瀏覽器。 您可以修改 [OutputCache] 屬性的 Location 屬性,以完全控制內容快取的位置。
您可以將 Location 屬性設定為下列任一值:
·任何
·客戶
·下游
·伺服器
·沒有
·ServerAndClient
根據預設,Location 屬性具有 Any 值。 不過,在某些情況下,您可能只想在瀏覽器或伺服器上快取。 例如,如果您要快取每個使用者個人化的資訊,則不應該快取伺服器上的資訊。 如果您要對不同的使用者顯示不同的資訊,您應該只快取用戶端上的資訊。
例如,清單 3 中的控制器會公開名為 GetName () 的動作,該動作會傳回目前的使用者名稱。 如果 Jack 登入網站並叫用 GetName () 巨集指令,則動作會傳回字串 「Hi Jack」。 如果 Jill 接著登入網站並叫用 GetName () 動作,則她也會取得字串 「Hi Jack」。 當 Jack 一開始叫用控制器動作之後,字串就會在網頁伺服器上快取給所有使用者。
清單 3 – Controllers\BadUserController.cs
using System.Web.Mvc;
using System.Web.UI;
namespace MvcApplication1.Controllers
{
public class BadUserController : Controller
{
[OutputCache(Duration = 3600, VaryByParam = "none")]
public string GetName()
{
return "Hi " + User.Identity.Name;
}
}
}
最有可能的是,清單 3 中的控制器無法以您想要的方式運作。 您不想將訊息 「Hi Jack」顯示給 Jill。
您不應該在伺服器快取中快取個人化內容。 不過,您可能想要快取瀏覽器快取中的個人化內容,以改善效能。 如果您在瀏覽器中快取內容,而使用者多次叫用相同的控制器動作,則可以從瀏覽器快取擷取內容,而不是伺服器。
清單 4 中修改過的控制器會快取 GetName () 動作的輸出。 不過,內容只會在瀏覽器上快取,而不是在伺服器上快取。 如此一來,當多個使用者叫用 GetName () 方法時,每位人員都會取得自己的使用者名稱,而不是另一個人的使用者名稱。
清單 4 – Controllers\UserController.cs
using System.Web.Mvc;
using System.Web.UI;
namespace MvcApplication1.Controllers
{
public class UserController : Controller
{
[OutputCache(Duration=3600, VaryByParam="none", Location=OutputCacheLocation.Client, NoStore=true)]
public string GetName()
{
return "Hi " + User.Identity.Name;
}
}
}
請注意,清單 4 中的 [OutputCache] 屬性包含設定為 OutputCacheLocation.Client 值的 Location 屬性。 [OutputCache] 屬性也包含 NoStore 屬性。 NoStore 屬性可用來通知 Proxy 伺服器和瀏覽器不應該儲存快取內容的永久複本。
改變輸出快取
在某些情況下,您可能會想要不同快取版本的相同內容。 例如,假設您正在建立主版/詳細資料頁面。 主版頁面會顯示電影標題清單。 當您按一下標題時,會取得所選電影的詳細資料。
如果您快取詳細資料頁面,則不論您按一下的電影為何,都會顯示相同電影的詳細資料。 第一位使用者選取的第一部電影將會顯示給所有未來的使用者。
您可以利用 [OutputCache] 屬性的 VaryByParam 屬性來修正此問題。 當表單參數或查詢字串參數不同時,此屬性可讓您建立相同內容的不同快取版本。
例如,清單 5 中的控制器會公開兩個名為 Master () 和 Details () 的動作。 Master () 巨集指令會傳回電影標題的清單,而 Details () 巨集指令會傳回所選電影的詳細資料。
清單 5 – Controllers\MoviesController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class MoviesController : Controller
{
private MovieDataContext _dataContext;
public MoviesController()
{
_dataContext = new MovieDataContext();
}
[OutputCache(Duration=int.MaxValue, VaryByParam="none")]
public ActionResult Master()
{
ViewData.Model = (from m in _dataContext.Movies
select m).ToList();
return View();
}
[OutputCache(Duration = int.MaxValue, VaryByParam = "id")]
public ActionResult Details(int id)
{
ViewData.Model = _dataContext.Movies.SingleOrDefault(m => m.Id == id);
return View();
}
}
}
Master () 巨集指令包含具有 「none」 值的 VaryByParam 屬性。 叫用 Master () 動作時,會傳回相同的主檢視快取版本。 任何表單參數或查詢字串參數都會忽略 (請參閱圖 2) 。
圖 2 – /Movies/Master 檢視
圖 3 – /Movies/Details 檢視
Details () 巨集指令包含具有 「Id」 值的 VaryByParam 屬性。 當 Id 參數的不同值傳遞至控制器動作時,會產生不同快取版本的 [詳細資料] 檢視。
請務必瞭解,使用 VaryByParam 屬性會產生較多的快取,而不是更少。 系統會針對每個不同版本的 Id 參數,建立不同的快取版本 [詳細資料] 檢視。
您可以將 VaryByParam 屬性設定為下列值:
* = 每當表單或查詢字串參數不同時,建立不同的快取版本。
none = 永不建立不同的快取版本
參數的分號清單 = 每當清單中的任何表單或查詢字串參數都不同時,建立不同的快取版本
建立快取設定檔
除了修改 [OutputCache] 屬性的屬性來設定輸出快取屬性,您也可以在 Web 組態 (web.config) 檔案中建立快取設定檔。 在 Web 組態檔中建立快取設定檔提供幾個重要的優點。
首先,藉由在 Web 組態檔中設定輸出快取,您可以控制控制器動作如何在單一中央位置快取內容。 您可以建立一個快取設定檔,並將設定檔套用至數個控制器或控制器動作。
其次,您可以修改 Web 組態檔,而不重新編譯您的應用程式。 如果您需要停用已部署至生產環境之應用程式的快取,您可以直接修改 Web 組態檔中定義的快取設定檔。 系統會自動偵測 Web 組態檔的任何變更並套用。
例如,清單 6 中的 < 快取 > Web 組態區段會定義名為 Cache1Hour 的快取設定檔。 快 < 取 > 區段必須出現在 Web 組態檔的 < system.web > 區段中。
清單 6 – web.config的快取區段
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Cache1Hour" duration="3600" varyByParam="none"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
清單 7 中的控制器說明如何使用 [OutputCache] 屬性,將 Cache1Hour 設定檔套用至控制器動作。
清單 7 – Controllers\ProfileController.cs
using System;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class ProfileController : Controller
{
[OutputCache(CacheProfile="Cache1Hour")]
public string Index()
{
return DateTime.Now.ToString("T");
}
}
}
如果您在清單 7 中叫用控制器公開的 Index () 巨集指令,則會傳回相同的時間 1 小時。
摘要
輸出快取提供非常簡單的方法,可大幅改善 ASP.NET MVC 應用程式的效能。 在本教學課程中,您已瞭解如何使用 [OutputCache] 屬性來快取控制器動作的輸出。 您也瞭解如何修改 [OutputCache] 屬性的屬性,例如 Duration 和 VaryByParam 屬性,以修改內容的快取方式。 最後,您已瞭解如何在 Web 組態檔中定義快取設定檔。